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
20class TestFaviconHandler;
21
22using content::FaviconURL;
23using content::NavigationEntry;
24using content::WebContents;
25
26namespace {
27
28// Fill the given bmp with valid png data.
29void 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.
44void 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
50void 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
68void 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.
77class 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.
132class 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
171class 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.
204class 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
334namespace {
335
336void HistoryRequestHandler::InvokeCallback() {
337  if (!callback_.is_null()) {
338    callback_.Run(history_results_);
339  }
340}
341
342void 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
364class 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
435TEST_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
476TEST_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
543TEST_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
626TEST_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
698TEST_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
760TEST_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
870TEST_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.*.
984TEST_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
1071static BrowserContextKeyedService* BuildFaviconService(
1072    content::BrowserContext* profile) {
1073  return new FaviconService(static_cast<Profile*>(profile));
1074}
1075
1076static 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.
1083TEST_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