Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/favicon_helper.h"
      6 
      7 #include "content/browser/renderer_host/test_render_view_host.h"
      8 #include "content/browser/tab_contents/navigation_entry.h"
      9 #include "content/browser/tab_contents/test_tab_contents.h"
     10 #include "ui/gfx/codec/png_codec.h"
     11 #include "ui/gfx/favicon_size.h"
     12 
     13 class TestFaviconHelper;
     14 
     15 namespace {
     16 
     17 // Fill the given bmp with valid png data.
     18 void FillDataToBitmap(int w, int h, SkBitmap* bmp) {
     19   bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h);
     20   bmp->allocPixels();
     21 
     22   unsigned char* src_data =
     23       reinterpret_cast<unsigned char*>(bmp->getAddr32(0, 0));
     24   for (int i = 0; i < w * h; i++) {
     25     src_data[i * 4 + 0] = static_cast<unsigned char>(i % 255);
     26     src_data[i * 4 + 1] = static_cast<unsigned char>(i % 255);
     27     src_data[i * 4 + 2] = static_cast<unsigned char>(i % 255);
     28     src_data[i * 4 + 3] = static_cast<unsigned char>(i % 255);
     29   }
     30 }
     31 
     32 // Fill the given data buffer with valid png data.
     33 void FillBitmap(int w, int h, std::vector<unsigned char>* output) {
     34   SkBitmap bitmap;
     35   FillDataToBitmap(w, h, &bitmap);
     36   gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, output);
     37 }
     38 
     39 // This class is used to save the download request for verifying with test case.
     40 // It also will be used to invoke the onDidDownload callback.
     41 class DownloadHandler {
     42  public:
     43   DownloadHandler(int download_id,
     44                   const GURL& image_url,
     45                   int image_size,
     46                   TestFaviconHelper* favicon_helper)
     47     : image_url_(image_url),
     48       image_size_(image_size),
     49       failed_(false),
     50       download_id_(download_id),
     51       favicon_helper_(favicon_helper) {
     52     FillDataToBitmap(16, 16, &bitmap_);
     53   }
     54 
     55   virtual ~DownloadHandler() {
     56   }
     57 
     58   static void UpdateFaviconURL(FaviconHelper* helper,
     59                                const std::vector<FaviconURL> urls);
     60 
     61   void InvokeCallback();
     62 
     63   void UpdateFaviconURL(const std::vector<FaviconURL> urls);
     64 
     65   const GURL image_url_;
     66   const int image_size_;
     67 
     68   // Simulates download failed or not.
     69   bool failed_;
     70 
     71  private:
     72   // Identified the specific download, will also be passed in
     73   // OnDidDownloadFavicon callback.
     74   int download_id_;
     75   TestFaviconHelper* favicon_helper_;
     76   SkBitmap bitmap_;
     77 
     78   DISALLOW_COPY_AND_ASSIGN(DownloadHandler);
     79 };
     80 
     81 // This class is used to save the history request for verifying with test case.
     82 // It also will be used to simulate the history response.
     83 class HistoryRequestHandler {
     84  public:
     85   HistoryRequestHandler(const GURL& page_url,
     86                         const GURL& icon_url,
     87                         int icon_type,
     88                         FaviconService::FaviconDataCallback* callback)
     89     : page_url_(page_url),
     90       icon_url_(icon_url),
     91       icon_type_(icon_type),
     92       callback_(callback) {
     93   }
     94 
     95   HistoryRequestHandler(const GURL& page_url,
     96                         const GURL& icon_url,
     97                         int icon_type,
     98                         const std::vector<unsigned char>& image_data,
     99                         FaviconService::FaviconDataCallback* callback)
    100     : page_url_(page_url),
    101       icon_url_(icon_url),
    102       icon_type_(icon_type),
    103       image_data_(image_data),
    104       callback_(callback) {
    105   }
    106 
    107   virtual ~HistoryRequestHandler() {
    108     delete callback_;
    109   }
    110   void InvokeCallback();
    111 
    112   const GURL page_url_;
    113   const GURL icon_url_;
    114   const int icon_type_;
    115   const std::vector<unsigned char> image_data_;
    116   history::FaviconData favicon_data_;
    117   FaviconService::FaviconDataCallback* callback_;
    118 
    119  private:
    120   DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler);
    121 };
    122 
    123 }  // namespace
    124 
    125 // This class is used to catch the FaviconHelper's download and history request,
    126 // and also provide the methods to access the FaviconHelper internal.
    127 class TestFaviconHelper : public FaviconHelper {
    128  public:
    129   TestFaviconHelper(const GURL& page_url,
    130                     TabContents* tab_contents,
    131                     Type type)
    132     : FaviconHelper(tab_contents, type),
    133       download_image_size_(0),
    134       download_id_(0),
    135       tab_contents_(tab_contents){
    136     entry_.set_url(page_url);
    137   }
    138 
    139   virtual ~TestFaviconHelper() {
    140   }
    141 
    142   HistoryRequestHandler* history_handler() {
    143     return history_handler_.get();
    144   }
    145 
    146   // This method will take the ownership of the given handler.
    147   void set_history_handler(HistoryRequestHandler* handler) {
    148     history_handler_.reset(handler);
    149   }
    150 
    151   DownloadHandler* download_handler() {
    152     return download_handler_.get();
    153   }
    154 
    155   // This method will take the ownership of the given download_handler.
    156   void set_download_handler(DownloadHandler* download_handler) {
    157     download_handler_.reset(download_handler);
    158   }
    159 
    160   virtual NavigationEntry* GetEntry() {
    161     return &entry_;
    162   }
    163 
    164   const std::vector<FaviconURL>& urls() {
    165     return urls_;
    166   }
    167 
    168   void FetchFavicon(const GURL& url) {
    169     FaviconHelper::FetchFavicon(url);
    170   }
    171 
    172   // The methods to access favicon internal.
    173   FaviconURL* current_candidate() {
    174     return FaviconHelper::current_candidate();
    175   }
    176 
    177   void OnDidDownloadFavicon(int id,
    178                             const GURL& image_url,
    179                             bool errored,
    180                             const SkBitmap& image) {
    181     FaviconHelper::OnDidDownloadFavicon(id, image_url, errored, image);
    182   }
    183 
    184  protected:
    185   virtual void UpdateFaviconMappingAndFetch(
    186       const GURL& page_url,
    187       const GURL& icon_url,
    188       history::IconType icon_type,
    189       CancelableRequestConsumerBase* consumer,
    190       FaviconService::FaviconDataCallback* callback) OVERRIDE {
    191     history_handler_.reset(new HistoryRequestHandler(page_url, icon_url,
    192                                                      icon_type, callback));
    193   }
    194 
    195   virtual void GetFavicon(
    196       const GURL& icon_url,
    197       history::IconType icon_type,
    198       CancelableRequestConsumerBase* consumer,
    199       FaviconService::FaviconDataCallback* callback) OVERRIDE {
    200     history_handler_.reset(new HistoryRequestHandler(GURL(), icon_url,
    201                                                      icon_type, callback));
    202   }
    203 
    204   virtual void GetFaviconForURL(
    205       const GURL& page_url,
    206       int icon_types,
    207       CancelableRequestConsumerBase* consumer,
    208       FaviconService::FaviconDataCallback* callback) OVERRIDE {
    209     history_handler_.reset(new HistoryRequestHandler(page_url, GURL(),
    210                                                      icon_types, callback));
    211   }
    212 
    213   virtual int DownloadFavicon(const GURL& image_url, int image_size) OVERRIDE {
    214     download_id_++;
    215     download_handler_.reset(new DownloadHandler(download_id_, image_url,
    216                                                 image_size, this));
    217     return download_id_;
    218   }
    219 
    220   virtual void SetHistoryFavicon(const GURL& page_url,
    221                                  const GURL& icon_url,
    222                                  const std::vector<unsigned char>& image_data,
    223                                  history::IconType icon_type) OVERRIDE {
    224     history_handler_.reset(new HistoryRequestHandler(page_url, icon_url,
    225         icon_type, image_data, NULL));
    226   }
    227 
    228   virtual FaviconService* GetFaviconService() OVERRIDE {
    229     // Just give none NULL value, so overridden methods can be hit.
    230     return (FaviconService*)(1);
    231   }
    232 
    233   virtual bool ShouldSaveFavicon(const GURL& url) OVERRIDE {
    234     return true;
    235   }
    236 
    237   GURL page_url_;
    238 
    239   GURL download_image_url_;
    240   int download_image_size_;
    241 
    242  private:
    243   NavigationEntry entry_;
    244 
    245   // The unique id of a download request. It will be returned to a
    246   // FaviconHelper.
    247   int download_id_;
    248 
    249   TabContents* tab_contents_;
    250   scoped_ptr<DownloadHandler> download_handler_;
    251   scoped_ptr<HistoryRequestHandler> history_handler_;
    252 
    253   DISALLOW_COPY_AND_ASSIGN(TestFaviconHelper);
    254 };
    255 
    256 namespace {
    257 
    258 void DownloadHandler::UpdateFaviconURL(FaviconHelper* helper,
    259                                        const std::vector<FaviconURL> urls) {
    260   helper->OnUpdateFaviconURL(0, urls);
    261 }
    262 
    263 void DownloadHandler::UpdateFaviconURL(const std::vector<FaviconURL> urls) {
    264   UpdateFaviconURL(favicon_helper_, urls);
    265 }
    266 
    267 void DownloadHandler::InvokeCallback() {
    268   favicon_helper_->OnDidDownloadFavicon(download_id_, image_url_, failed_,
    269                                         bitmap_);
    270 }
    271 
    272 void HistoryRequestHandler::InvokeCallback() {
    273   callback_->Run(0, favicon_data_);
    274 }
    275 
    276 class FaviconHelperTest : public RenderViewHostTestHarness {
    277 };
    278 
    279 TEST_F(FaviconHelperTest, GetFaviconFromHistory) {
    280   const GURL page_url("http://www.google.com");
    281   const GURL icon_url("http://www.google.com/favicon");
    282 
    283   TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON);
    284 
    285   helper.FetchFavicon(page_url);
    286   HistoryRequestHandler* history_handler = helper.history_handler();
    287   // Ensure the data given to history is correct.
    288   ASSERT_TRUE(history_handler);
    289   EXPECT_EQ(page_url, history_handler->page_url_);
    290   EXPECT_EQ(GURL(), history_handler->icon_url_);
    291   EXPECT_EQ(history::FAVICON, history_handler->icon_type_);
    292 
    293   // Set valid icon data.
    294   history_handler->favicon_data_.known_icon = true;
    295   history_handler->favicon_data_.icon_type = history::FAVICON;
    296   history_handler->favicon_data_.expired = false;
    297   history_handler->favicon_data_.icon_url = icon_url;
    298   scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
    299   FillBitmap(kFaviconSize, kFaviconSize, &data->data);
    300   history_handler->favicon_data_.image_data = data;
    301 
    302   // Send history response.
    303   history_handler->InvokeCallback();
    304   // Verify FaviconHelper status
    305   EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
    306   EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
    307 
    308   // Simulates update favicon url.
    309   std::vector<FaviconURL> urls;
    310   urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON));
    311   DownloadHandler::UpdateFaviconURL(&helper, urls);
    312 
    313   // Verify FaviconHelper status
    314   EXPECT_EQ(1U, helper.urls().size());
    315   ASSERT_TRUE(helper.current_candidate());
    316   ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
    317   ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
    318 
    319   // Favicon shouldn't request to download icon.
    320   DownloadHandler* download_handler = helper.download_handler();
    321   ASSERT_FALSE(download_handler);
    322 }
    323 
    324 TEST_F(FaviconHelperTest, DownloadFavicon) {
    325   const GURL page_url("http://www.google.com");
    326   const GURL icon_url("http://www.google.com/favicon");
    327 
    328   TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON);
    329 
    330   helper.FetchFavicon(page_url);
    331   HistoryRequestHandler* history_handler = helper.history_handler();
    332   // Ensure the data given to history is correct.
    333   ASSERT_TRUE(history_handler);
    334   EXPECT_EQ(page_url, history_handler->page_url_);
    335   EXPECT_EQ(GURL(), history_handler->icon_url_);
    336   EXPECT_EQ(history::FAVICON, history_handler->icon_type_);
    337 
    338   // Set icon data expired
    339   history_handler->favicon_data_.known_icon = true;
    340   history_handler->favicon_data_.icon_type = history::FAVICON;
    341   history_handler->favicon_data_.expired = true;
    342   history_handler->favicon_data_.icon_url = icon_url;
    343   // Send history response.
    344   history_handler->InvokeCallback();
    345   // Verify FaviconHelper status
    346   EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
    347   EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
    348 
    349   // Simulates update favicon url.
    350   std::vector<FaviconURL> urls;
    351   urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON));
    352   DownloadHandler::UpdateFaviconURL(&helper, urls);
    353 
    354   // Verify FaviconHelper status
    355   EXPECT_EQ(1U, helper.urls().size());
    356   ASSERT_TRUE(helper.current_candidate());
    357   ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
    358   ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
    359 
    360   // Favicon should request to download icon now.
    361   DownloadHandler* download_handler = helper.download_handler();
    362   ASSERT_TRUE(download_handler);
    363   // Verify the download request.
    364   EXPECT_EQ(icon_url, download_handler->image_url_);
    365   EXPECT_EQ(kFaviconSize, download_handler->image_size_);
    366 
    367   // Reset the history_handler to verify whether favicon is set.
    368   helper.set_history_handler(NULL);
    369 
    370   // Smulates download done.
    371   download_handler->InvokeCallback();
    372 
    373   // New icon should be saved to history backend and navigation entry.
    374   history_handler = helper.history_handler();
    375   ASSERT_TRUE(history_handler);
    376   EXPECT_EQ(icon_url, history_handler->icon_url_);
    377   EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
    378   EXPECT_LT(0U, history_handler->image_data_.size());
    379   EXPECT_EQ(page_url, history_handler->page_url_);
    380 
    381   // Verify NavigationEntry.
    382   EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
    383   EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
    384   EXPECT_FALSE(helper.GetEntry()->favicon().bitmap().empty());
    385 }
    386 
    387 TEST_F(FaviconHelperTest, UpdateAndDownloadFavicon) {
    388   const GURL page_url("http://www.google.com");
    389   const GURL icon_url("http://www.google.com/favicon");
    390   const GURL new_icon_url("http://www.google.com/new_favicon");
    391 
    392   TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON);
    393 
    394   helper.FetchFavicon(page_url);
    395   HistoryRequestHandler* history_handler = helper.history_handler();
    396   // Ensure the data given to history is correct.
    397   ASSERT_TRUE(history_handler);
    398   EXPECT_EQ(page_url, history_handler->page_url_);
    399   EXPECT_EQ(GURL(), history_handler->icon_url_);
    400   EXPECT_EQ(history::FAVICON, history_handler->icon_type_);
    401 
    402   // Set valid icon data.
    403   history_handler->favicon_data_.known_icon = true;
    404   history_handler->favicon_data_.icon_type = history::FAVICON;
    405   history_handler->favicon_data_.expired = false;
    406   history_handler->favicon_data_.icon_url = icon_url;
    407   scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
    408   FillBitmap(kFaviconSize, kFaviconSize, &data->data);
    409   history_handler->favicon_data_.image_data = data;
    410 
    411   // Send history response.
    412   history_handler->InvokeCallback();
    413   // Verify FaviconHelper status.
    414   EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
    415   EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
    416 
    417   // Reset the history_handler to verify whether new icon is requested from
    418   // history.
    419   helper.set_history_handler(NULL);
    420 
    421   // Simulates update with the different favicon url.
    422   std::vector<FaviconURL> urls;
    423   urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
    424   DownloadHandler::UpdateFaviconURL(&helper, urls);
    425 
    426   // Verify FaviconHelper status.
    427   EXPECT_EQ(1U, helper.urls().size());
    428   ASSERT_TRUE(helper.current_candidate());
    429   ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url);
    430   ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
    431   // The favicon status's url should be updated.
    432   ASSERT_EQ(new_icon_url, helper.GetEntry()->favicon().url());
    433 
    434   // Favicon should be requested from history.
    435   history_handler = helper.history_handler();
    436   ASSERT_TRUE(history_handler);
    437   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    438   EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
    439   EXPECT_EQ(page_url, history_handler->page_url_);
    440 
    441   // Simulate not find icon.
    442   history_handler->favicon_data_.known_icon = false;
    443   history_handler->InvokeCallback();
    444 
    445   // Favicon should request to download icon now.
    446   DownloadHandler* download_handler = helper.download_handler();
    447   ASSERT_TRUE(download_handler);
    448   // Verify the download request.
    449   EXPECT_EQ(new_icon_url, download_handler->image_url_);
    450   EXPECT_EQ(kFaviconSize, download_handler->image_size_);
    451 
    452   // Reset the history_handler to verify whether favicon is set.
    453   helper.set_history_handler(NULL);
    454 
    455   // Smulates download done.
    456   download_handler->InvokeCallback();
    457 
    458   // New icon should be saved to history backend and navigation entry.
    459   history_handler = helper.history_handler();
    460   ASSERT_TRUE(history_handler);
    461   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    462   EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
    463   EXPECT_LT(0U, history_handler->image_data_.size());
    464   EXPECT_EQ(page_url, history_handler->page_url_);
    465 
    466   // Verify NavigationEntry.
    467   EXPECT_EQ(new_icon_url, helper.GetEntry()->favicon().url());
    468   EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
    469   EXPECT_FALSE(helper.GetEntry()->favicon().bitmap().empty());
    470 }
    471 
    472 TEST_F(FaviconHelperTest, UpdateFavicon) {
    473   const GURL page_url("http://www.google.com");
    474   const GURL icon_url("http://www.google.com/favicon");
    475   const GURL new_icon_url("http://www.google.com/new_favicon");
    476 
    477   TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON);
    478 
    479   helper.FetchFavicon(page_url);
    480   HistoryRequestHandler* history_handler = helper.history_handler();
    481   // Ensure the data given to history is correct.
    482   ASSERT_TRUE(history_handler);
    483   EXPECT_EQ(page_url, history_handler->page_url_);
    484   EXPECT_EQ(GURL(), history_handler->icon_url_);
    485   EXPECT_EQ(history::FAVICON, history_handler->icon_type_);
    486 
    487   // Set valid icon data.
    488   history_handler->favicon_data_.known_icon = true;
    489   history_handler->favicon_data_.icon_type = history::FAVICON;
    490   history_handler->favicon_data_.expired = false;
    491   history_handler->favicon_data_.icon_url = icon_url;
    492   scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
    493   FillBitmap(kFaviconSize, kFaviconSize, &data->data);
    494   history_handler->favicon_data_.image_data = data;
    495 
    496   // Send history response.
    497   history_handler->InvokeCallback();
    498   // Verify FaviconHelper status.
    499   EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
    500   EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url());
    501 
    502   // Reset the history_handler to verify whether new icon is requested from
    503   // history.
    504   helper.set_history_handler(NULL);
    505 
    506   // Simulates update with the different favicon url.
    507   std::vector<FaviconURL> urls;
    508   urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
    509   DownloadHandler::UpdateFaviconURL(&helper, urls);
    510 
    511   // Verify FaviconHelper status.
    512   EXPECT_EQ(1U, helper.urls().size());
    513   ASSERT_TRUE(helper.current_candidate());
    514   ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url);
    515   ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
    516   // The favicon status's url should be updated.
    517   ASSERT_EQ(new_icon_url, helper.GetEntry()->favicon().url());
    518 
    519   // Favicon should be requested from history.
    520   history_handler = helper.history_handler();
    521   ASSERT_TRUE(history_handler);
    522   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    523   EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
    524   EXPECT_EQ(page_url, history_handler->page_url_);
    525 
    526   // Simulate find icon.
    527   history_handler->favicon_data_.known_icon = true;
    528   history_handler->favicon_data_.icon_type = history::FAVICON;
    529   history_handler->favicon_data_.expired = false;
    530   history_handler->favicon_data_.icon_url = new_icon_url;
    531   history_handler->favicon_data_.image_data = data;
    532   history_handler->InvokeCallback();
    533 
    534   // Shouldn't request download favicon
    535   EXPECT_FALSE(helper.download_handler());
    536 
    537   // Verify the favicon status.
    538   EXPECT_EQ(new_icon_url, helper.GetEntry()->favicon().url());
    539   EXPECT_TRUE(helper.GetEntry()->favicon().is_valid());
    540   EXPECT_FALSE(helper.GetEntry()->favicon().bitmap().empty());
    541 }
    542 
    543 TEST_F(FaviconHelperTest, Download2ndFaviconURLCandidate) {
    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   TestFaviconHelper helper(page_url, contents(), FaviconHelper::TOUCH);
    549 
    550   helper.FetchFavicon(page_url);
    551   HistoryRequestHandler* history_handler = helper.history_handler();
    552   // Ensure the data given to history is correct.
    553   ASSERT_TRUE(history_handler);
    554   EXPECT_EQ(page_url, history_handler->page_url_);
    555   EXPECT_EQ(GURL(), history_handler->icon_url_);
    556   EXPECT_EQ(history::TOUCH_PRECOMPOSED_ICON | history::TOUCH_ICON,
    557             history_handler->icon_type_);
    558 
    559   // Icon not found.
    560   history_handler->favicon_data_.known_icon = false;
    561   // Send history response.
    562   history_handler->InvokeCallback();
    563   // Verify FaviconHelper status.
    564   EXPECT_FALSE(helper.GetEntry()->favicon().is_valid());
    565   EXPECT_EQ(GURL(), helper.GetEntry()->favicon().url());
    566 
    567   // Reset the history_handler to verify whether new icon is requested from
    568   // history.
    569   helper.set_history_handler(NULL);
    570 
    571   // Simulates update with the different favicon url.
    572   std::vector<FaviconURL> urls;
    573   urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON));
    574   urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON));
    575   urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
    576 
    577   DownloadHandler::UpdateFaviconURL(&helper, urls);
    578 
    579   // Verify FaviconHelper status.
    580   EXPECT_EQ(2U, helper.urls().size());
    581   ASSERT_TRUE(helper.current_candidate());
    582   ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
    583   ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON,
    584             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(icon_url, history_handler->icon_url_);
    590   EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_);
    591   EXPECT_EQ(page_url, history_handler->page_url_);
    592 
    593   // Simulate not find icon.
    594   history_handler->favicon_data_.known_icon = false;
    595   history_handler->InvokeCallback();
    596 
    597   // Should request download favicon.
    598   DownloadHandler* download_handler = helper.download_handler();
    599   EXPECT_TRUE(download_handler);
    600   // Verify the download request.
    601   EXPECT_EQ(icon_url, download_handler->image_url_);
    602   EXPECT_EQ(0, download_handler->image_size_);
    603 
    604   // Reset the history_handler to verify whether favicon is request from
    605   // history.
    606   helper.set_history_handler(NULL);
    607   // Smulates download failed.
    608   download_handler->failed_ = true;
    609   download_handler->InvokeCallback();
    610 
    611   // Left 1 url.
    612   EXPECT_EQ(1U, helper.urls().size());
    613   ASSERT_TRUE(helper.current_candidate());
    614   EXPECT_EQ(new_icon_url, helper.current_candidate()->icon_url);
    615   EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type);
    616 
    617   // Favicon should be requested from history.
    618   history_handler = helper.history_handler();
    619   ASSERT_TRUE(history_handler);
    620   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    621   EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
    622   EXPECT_EQ(page_url, history_handler->page_url_);
    623 
    624   // Reset download handler
    625   helper.set_download_handler(NULL);
    626 
    627   // Smulates getting a expired icon from history.
    628   history_handler->favicon_data_.known_icon = true;
    629   history_handler->favicon_data_.icon_type = history::TOUCH_ICON;
    630   history_handler->favicon_data_.expired = true;
    631   history_handler->favicon_data_.icon_url = new_icon_url;
    632   scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
    633   FillBitmap(kFaviconSize, kFaviconSize, &data->data);
    634   history_handler->favicon_data_.image_data = data;
    635   history_handler->InvokeCallback();
    636 
    637   // Verify the download request.
    638   download_handler = helper.download_handler();
    639   EXPECT_TRUE(download_handler);
    640   EXPECT_EQ(new_icon_url, download_handler->image_url_);
    641   EXPECT_EQ(0, download_handler->image_size_);
    642 
    643   helper.set_history_handler(NULL);
    644 
    645   // Simulates icon being downloaded.
    646   download_handler->InvokeCallback();
    647 
    648   // New icon should be saved to history backend.
    649   history_handler = helper.history_handler();
    650   ASSERT_TRUE(history_handler);
    651   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    652   EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
    653   EXPECT_LT(0U, history_handler->image_data_.size());
    654   EXPECT_EQ(page_url, history_handler->page_url_);
    655 }
    656 
    657 TEST_F(FaviconHelperTest, UpdateDuringDownloading) {
    658   const GURL page_url("http://www.google.com");
    659   const GURL icon_url("http://www.google.com/favicon");
    660   const GURL new_icon_url("http://www.google.com/new_favicon");
    661 
    662   TestFaviconHelper helper(page_url, contents(), FaviconHelper::TOUCH);
    663 
    664   helper.FetchFavicon(page_url);
    665   HistoryRequestHandler* history_handler = helper.history_handler();
    666   // Ensure the data given to history is correct.
    667   ASSERT_TRUE(history_handler);
    668   EXPECT_EQ(page_url, history_handler->page_url_);
    669   EXPECT_EQ(GURL(), history_handler->icon_url_);
    670   EXPECT_EQ(history::TOUCH_PRECOMPOSED_ICON | history::TOUCH_ICON,
    671             history_handler->icon_type_);
    672 
    673   // Icon not found.
    674   history_handler->favicon_data_.known_icon = false;
    675   // Send history response.
    676   history_handler->InvokeCallback();
    677   // Verify FaviconHelper status.
    678   EXPECT_FALSE(helper.GetEntry()->favicon().is_valid());
    679   EXPECT_EQ(GURL(), helper.GetEntry()->favicon().url());
    680 
    681   // Reset the history_handler to verify whether new icon is requested from
    682   // history.
    683   helper.set_history_handler(NULL);
    684 
    685   // Simulates update with the different favicon url.
    686   std::vector<FaviconURL> urls;
    687   urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON));
    688   urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON));
    689   urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
    690 
    691   DownloadHandler::UpdateFaviconURL(&helper, urls);
    692 
    693   // Verify FaviconHelper status.
    694   EXPECT_EQ(2U, helper.urls().size());
    695   ASSERT_TRUE(helper.current_candidate());
    696   ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
    697   ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON,
    698             helper.current_candidate()->icon_type);
    699 
    700   // Favicon should be requested from history.
    701   history_handler = helper.history_handler();
    702   ASSERT_TRUE(history_handler);
    703   EXPECT_EQ(icon_url, history_handler->icon_url_);
    704   EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_);
    705   EXPECT_EQ(page_url, history_handler->page_url_);
    706 
    707   // Simulate not find icon.
    708   history_handler->favicon_data_.known_icon = false;
    709   history_handler->InvokeCallback();
    710 
    711   // Should request download favicon.
    712   DownloadHandler* download_handler = helper.download_handler();
    713   EXPECT_TRUE(download_handler);
    714   // Verify the download request.
    715   EXPECT_EQ(icon_url, download_handler->image_url_);
    716   EXPECT_EQ(0, download_handler->image_size_);
    717 
    718   // Reset the history_handler to verify whether favicon is request from
    719   // history.
    720   helper.set_history_handler(NULL);
    721   const GURL latest_icon_url("http://www.google.com/latest_favicon");
    722   std::vector<FaviconURL> latest_urls;
    723   latest_urls.push_back(FaviconURL(latest_icon_url, FaviconURL::TOUCH_ICON));
    724   DownloadHandler::UpdateFaviconURL(&helper, latest_urls);
    725   EXPECT_EQ(1U, helper.urls().size());
    726   EXPECT_EQ(latest_icon_url, helper.current_candidate()->icon_url);
    727   EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type);
    728 
    729   // Whether new icon is requested from history
    730   history_handler = helper.history_handler();
    731   ASSERT_TRUE(history_handler);
    732   EXPECT_EQ(latest_icon_url, history_handler->icon_url_);
    733   EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
    734   EXPECT_EQ(page_url, history_handler->page_url_);
    735 
    736   // Reset the history_handler to verify whether favicon is request from
    737   // history.
    738   // Save the callback for late use.
    739   FaviconService::FaviconDataCallback* callback = history_handler->callback_;
    740   // Prevent the callback from being released.
    741   history_handler->callback_ = NULL;
    742   helper.set_history_handler(NULL);
    743 
    744   // Smulates download succeed.
    745   download_handler->InvokeCallback();
    746   // The downloaded icon should be thrown away as there is faviocn update.
    747   EXPECT_FALSE(helper.history_handler());
    748 
    749   helper.set_download_handler(NULL);
    750 
    751   // Smulates getting the icon from history.
    752   scoped_ptr<HistoryRequestHandler> handler;
    753   handler.reset(new HistoryRequestHandler(page_url, latest_icon_url,
    754                                           history::TOUCH_ICON, callback));
    755   handler->favicon_data_.known_icon = true;
    756   handler->favicon_data_.expired = false;
    757   handler->favicon_data_.icon_type = history::TOUCH_ICON;
    758   handler->favicon_data_.icon_url = latest_icon_url;
    759   scoped_refptr<RefCountedBytes> data = new RefCountedBytes();
    760   FillBitmap(kFaviconSize, kFaviconSize, &data->data);
    761   handler->favicon_data_.image_data = data;
    762 
    763   handler->InvokeCallback();
    764 
    765   // No download request.
    766   EXPECT_FALSE(helper.download_handler());
    767 }
    768 
    769 }  // namespace.
    770