Renamed FaviconHandlerDelegate to FaviconDriver.
[chromium-blink-merge.git] / chrome / browser / favicon / favicon_handler_unittest.cc
blob3fadf19386f22e983ee33a5214b5263dd21c413e
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.
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"
20 class TestFaviconHandler;
22 using content::FaviconURL;
23 using content::NavigationEntry;
24 using content::WebContents;
26 namespace {
28 // Fill the given bmp with valid png data.
29 void FillDataToBitmap(int w, int h, SkBitmap* bmp) {
30 bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h);
31 bmp->allocPixels();
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);
43 // Fill the given data buffer with valid png data.
44 void FillBitmap(int w, int h, std::vector<unsigned char>* output) {
45 SkBitmap bitmap;
46 FillDataToBitmap(w, h, &bitmap);
47 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, output);
50 void SetFaviconBitmapResult(
51 const GURL& icon_url,
52 favicon_base::IconType icon_type,
53 bool expired,
54 std::vector<favicon_base::FaviconBitmapResult>* favicon_bitmap_results) {
55 scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
56 FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data());
57 favicon_base::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;
65 favicon_bitmap_results->push_back(bitmap_result);
68 void SetFaviconBitmapResult(
69 const GURL& icon_url,
70 std::vector<favicon_base::FaviconBitmapResult>* favicon_bitmap_results) {
71 SetFaviconBitmapResult(icon_url,
72 favicon_base::FAVICON,
73 false /* expired */,
74 favicon_bitmap_results);
77 // This class is used to save the download request for verifying with test case.
78 // It also will be used to invoke the onDidDownload callback.
79 class DownloadHandler {
80 public:
81 explicit DownloadHandler(TestFaviconHandler* favicon_helper)
82 : favicon_helper_(favicon_helper),
83 failed_(false) {
86 virtual ~DownloadHandler() {
89 void Reset() {
90 download_.reset(NULL);
91 failed_ = false;
94 void AddDownload(
95 int download_id,
96 const GURL& image_url,
97 const std::vector<int>& image_sizes,
98 int max_image_size) {
99 download_.reset(new Download(
100 download_id, image_url, image_sizes, max_image_size, false));
103 void InvokeCallback();
105 void set_failed(bool failed) { failed_ = failed; }
107 bool HasDownload() const { return download_.get() != NULL; }
108 const GURL& GetImageUrl() const { return download_->image_url; }
109 void SetImageSizes(const std::vector<int>& sizes) {
110 download_->image_sizes = sizes; }
112 private:
113 struct Download {
114 Download(int id,
115 GURL url,
116 const std::vector<int>& sizes,
117 int max_size,
118 bool failed)
119 : download_id(id),
120 image_url(url),
121 image_sizes(sizes),
122 max_image_size(max_size) {}
123 ~Download() {}
124 int download_id;
125 GURL image_url;
126 std::vector<int> image_sizes;
127 int max_image_size;
130 TestFaviconHandler* favicon_helper_;
131 scoped_ptr<Download> download_;
132 bool failed_;
134 DISALLOW_COPY_AND_ASSIGN(DownloadHandler);
137 // This class is used to save the history request for verifying with test case.
138 // It also will be used to simulate the history response.
139 class HistoryRequestHandler {
140 public:
141 HistoryRequestHandler(const GURL& page_url,
142 const GURL& icon_url,
143 int icon_type,
144 const FaviconService::FaviconResultsCallback& callback)
145 : page_url_(page_url),
146 icon_url_(icon_url),
147 icon_type_(icon_type),
148 callback_(callback) {
151 HistoryRequestHandler(const GURL& page_url,
152 const GURL& icon_url,
153 int icon_type,
154 const std::vector<unsigned char>& bitmap_data,
155 const gfx::Size& size)
156 : page_url_(page_url),
157 icon_url_(icon_url),
158 icon_type_(icon_type),
159 bitmap_data_(bitmap_data),
160 size_(size) {
163 virtual ~HistoryRequestHandler() {}
164 void InvokeCallback();
166 const GURL page_url_;
167 const GURL icon_url_;
168 const int icon_type_;
169 const std::vector<unsigned char> bitmap_data_;
170 const gfx::Size size_;
171 std::vector<favicon_base::FaviconBitmapResult> history_results_;
172 FaviconService::FaviconResultsCallback callback_;
174 private:
175 DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler);
178 } // namespace
180 class TestFaviconClient : public FaviconClient {
181 public:
182 virtual ~TestFaviconClient() {};
184 virtual FaviconService* GetFaviconService() OVERRIDE {
185 // Just give none NULL value, so overridden methods can be hit.
186 return (FaviconService*)(1);
189 virtual bool IsBookmarked(const GURL& url) OVERRIDE { return false; }
192 class TestFaviconDriver : public FaviconDriver {
193 public:
194 TestFaviconDriver() {
197 virtual ~TestFaviconDriver() {
200 virtual bool IsOffTheRecord() OVERRIDE { return false; }
202 virtual NavigationEntry* GetActiveEntry() OVERRIDE {
203 ADD_FAILURE() << "TestFaviconDriver::GetActiveEntry() "
204 << "should never be called in tests.";
205 return NULL;
208 virtual int StartDownload(const GURL& url,
209 int max_bitmap_size) OVERRIDE {
210 ADD_FAILURE() << "TestFaviconDriver::StartDownload() "
211 << "should never be called in tests.";
212 return -1;
215 virtual void NotifyFaviconUpdated(bool icon_url_changed) OVERRIDE {
216 ADD_FAILURE() << "TestFaviconDriver::NotifyFaviconUpdated() "
217 << "should never be called in tests.";
220 private:
221 DISALLOW_COPY_AND_ASSIGN(TestFaviconDriver);
224 // This class is used to catch the FaviconHandler's download and history
225 // request, and also provide the methods to access the FaviconHandler
226 // internals.
227 class TestFaviconHandler : public FaviconHandler {
228 public:
229 TestFaviconHandler(const GURL& page_url,
230 FaviconClient* client,
231 FaviconDriver* driver,
232 Type type,
233 bool download_largest_icon)
234 : FaviconHandler(client, driver, type,
235 download_largest_icon),
236 entry_(NavigationEntry::Create()),
237 download_id_(0),
238 num_favicon_updates_(0) {
239 entry_->SetURL(page_url);
240 download_handler_.reset(new DownloadHandler(this));
243 virtual ~TestFaviconHandler() {
246 HistoryRequestHandler* history_handler() {
247 return history_handler_.get();
250 // This method will take the ownership of the given handler.
251 void set_history_handler(HistoryRequestHandler* handler) {
252 history_handler_.reset(handler);
255 DownloadHandler* download_handler() {
256 return download_handler_.get();
259 size_t num_favicon_update_notifications() const {
260 return num_favicon_updates_;
263 void ResetNumFaviconUpdateNotifications() {
264 num_favicon_updates_ = 0;
267 // Methods to access favicon internals.
268 virtual NavigationEntry* GetEntry() OVERRIDE {
269 return entry_.get();
272 const std::vector<FaviconURL>& urls() {
273 return image_urls_;
276 FaviconURL* current_candidate() {
277 return FaviconHandler::current_candidate();
280 const FaviconCandidate& best_favicon_candidate() {
281 return best_favicon_candidate_;
284 protected:
285 virtual void UpdateFaviconMappingAndFetch(
286 const GURL& page_url,
287 const GURL& icon_url,
288 favicon_base::IconType icon_type,
289 const FaviconService::FaviconResultsCallback& callback,
290 base::CancelableTaskTracker* tracker) OVERRIDE {
291 history_handler_.reset(new HistoryRequestHandler(page_url, icon_url,
292 icon_type, callback));
295 virtual void GetFaviconFromFaviconService(
296 const GURL& icon_url,
297 favicon_base::IconType icon_type,
298 const FaviconService::FaviconResultsCallback& callback,
299 base::CancelableTaskTracker* tracker) OVERRIDE {
300 history_handler_.reset(new HistoryRequestHandler(GURL(), icon_url,
301 icon_type, callback));
304 virtual void GetFaviconForURLFromFaviconService(
305 const GURL& page_url,
306 int icon_types,
307 const FaviconService::FaviconResultsCallback& callback,
308 base::CancelableTaskTracker* tracker) OVERRIDE {
309 history_handler_.reset(new HistoryRequestHandler(page_url, GURL(),
310 icon_types, callback));
313 virtual int DownloadFavicon(const GURL& image_url,
314 int max_bitmap_size) OVERRIDE {
315 download_id_++;
316 std::vector<int> sizes;
317 sizes.push_back(0);
318 download_handler_->AddDownload(
319 download_id_, image_url, sizes, max_bitmap_size);
320 return download_id_;
323 virtual void SetHistoryFavicons(const GURL& page_url,
324 const GURL& icon_url,
325 favicon_base::IconType icon_type,
326 const gfx::Image& image) OVERRIDE {
327 scoped_refptr<base::RefCountedMemory> bytes = image.As1xPNGBytes();
328 std::vector<unsigned char> bitmap_data(bytes->front(),
329 bytes->front() + bytes->size());
330 history_handler_.reset(new HistoryRequestHandler(
331 page_url, icon_url, icon_type, bitmap_data, image.Size()));
334 virtual bool ShouldSaveFavicon(const GURL& url) OVERRIDE {
335 return true;
338 virtual void NotifyFaviconUpdated(bool icon_url_changed) OVERRIDE {
339 ++num_favicon_updates_;
342 GURL page_url_;
344 private:
345 scoped_ptr<NavigationEntry> entry_;
347 // The unique id of a download request. It will be returned to a
348 // FaviconHandler.
349 int download_id_;
351 scoped_ptr<DownloadHandler> download_handler_;
352 scoped_ptr<HistoryRequestHandler> history_handler_;
354 // The number of times that NotifyFaviconUpdated() has been called.
355 size_t num_favicon_updates_;
357 DISALLOW_COPY_AND_ASSIGN(TestFaviconHandler);
360 namespace {
362 void HistoryRequestHandler::InvokeCallback() {
363 if (!callback_.is_null()) {
364 callback_.Run(history_results_);
368 void DownloadHandler::InvokeCallback() {
369 std::vector<gfx::Size> original_bitmap_sizes;
370 std::vector<SkBitmap> bitmaps;
371 if (!failed_) {
372 for (std::vector<int>::const_iterator i = download_->image_sizes.begin();
373 i != download_->image_sizes.end(); ++i) {
374 int original_size = (*i > 0) ? *i : gfx::kFaviconSize;
375 int downloaded_size = original_size;
376 if (download_->max_image_size != 0 &&
377 downloaded_size > download_->max_image_size) {
378 downloaded_size = download_->max_image_size;
380 SkBitmap bitmap;
381 FillDataToBitmap(downloaded_size, downloaded_size, &bitmap);
382 bitmaps.push_back(bitmap);
383 original_bitmap_sizes.push_back(gfx::Size(original_size, original_size));
386 favicon_helper_->OnDidDownloadFavicon(download_->download_id,
387 download_->image_url,
388 bitmaps,
389 original_bitmap_sizes);
392 class FaviconHandlerTest : public ChromeRenderViewHostTestHarness {
393 public:
394 FaviconHandlerTest() {
397 virtual ~FaviconHandlerTest() {
400 // Simulates requesting a favicon for |page_url| given:
401 // - We have not previously cached anything in history for |page_url| or for
402 // any of |candidates|.
403 // - The page provides favicons at |candidate_icons|.
404 // - The favicons at |candidate_icons| have edge pixel sizes of
405 // |candidate_icon_sizes|.
406 void DownloadTillDoneIgnoringHistory(
407 TestFaviconHandler* favicon_handler,
408 const GURL& page_url,
409 const std::vector<FaviconURL>& candidate_icons,
410 const int* candidate_icon_sizes) {
411 UpdateFaviconURL(favicon_handler, page_url, candidate_icons);
412 EXPECT_EQ(candidate_icons.size(), favicon_handler->image_urls().size());
414 DownloadHandler* download_handler = favicon_handler->download_handler();
415 for (size_t i = 0; i < candidate_icons.size(); ++i) {
416 favicon_handler->history_handler()->history_results_.clear();
417 favicon_handler->history_handler()->InvokeCallback();
418 ASSERT_TRUE(download_handler->HasDownload());
419 EXPECT_EQ(download_handler->GetImageUrl(),
420 candidate_icons[i].icon_url);
421 std::vector<int> sizes;
422 sizes.push_back(candidate_icon_sizes[i]);
423 download_handler->SetImageSizes(sizes);
424 download_handler->InvokeCallback();
426 if (favicon_handler->num_favicon_update_notifications())
427 return;
431 void UpdateFaviconURL(
432 TestFaviconHandler* favicon_handler,
433 const GURL& page_url,
434 const std::vector<FaviconURL>& candidate_icons) {
435 favicon_handler->ResetNumFaviconUpdateNotifications();
437 favicon_handler->FetchFavicon(page_url);
438 favicon_handler->history_handler()->InvokeCallback();
440 favicon_handler->OnUpdateFaviconURL(0, candidate_icons);
443 virtual void SetUp() {
444 // The score computed by SelectFaviconFrames() is dependent on the supported
445 // scale factors of the platform. It is used for determining the goodness of
446 // a downloaded bitmap in FaviconHandler::OnDidDownloadFavicon().
447 // Force the values of the scale factors so that the tests produce the same
448 // results on all platforms.
449 std::vector<ui::ScaleFactor> scale_factors;
450 scale_factors.push_back(ui::SCALE_FACTOR_100P);
451 scoped_set_supported_scale_factors_.reset(
452 new ui::test::ScopedSetSupportedScaleFactors(scale_factors));
454 ChromeRenderViewHostTestHarness::SetUp();
457 virtual void TearDown() OVERRIDE {
458 Profile* profile = Profile::FromBrowserContext(
459 web_contents()->GetBrowserContext());
460 FaviconServiceFactory::GetInstance()->SetTestingFactory(
461 profile, NULL);
462 ChromeRenderViewHostTestHarness::TearDown();
465 private:
466 typedef scoped_ptr<ui::test::ScopedSetSupportedScaleFactors>
467 ScopedSetSupportedScaleFactors;
468 ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_;
469 DISALLOW_COPY_AND_ASSIGN(FaviconHandlerTest);
472 TEST_F(FaviconHandlerTest, GetFaviconFromHistory) {
473 const GURL page_url("http://www.google.com");
474 const GURL icon_url("http://www.google.com/favicon");
476 TestFaviconDriver driver;
477 TestFaviconClient client;
478 TestFaviconHandler helper(
479 page_url, &client, &driver, FaviconHandler::FAVICON, false);
481 helper.FetchFavicon(page_url);
482 HistoryRequestHandler* history_handler = helper.history_handler();
483 // Ensure the data given to history is correct.
484 ASSERT_TRUE(history_handler);
485 EXPECT_EQ(page_url, history_handler->page_url_);
486 EXPECT_EQ(GURL(), history_handler->icon_url_);
487 EXPECT_EQ(favicon_base::FAVICON, history_handler->icon_type_);
489 SetFaviconBitmapResult(icon_url, &history_handler->history_results_);
491 // Send history response.
492 history_handler->InvokeCallback();
493 // Verify FaviconHandler status
494 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
495 EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url);
497 // Simulates update favicon url.
498 std::vector<FaviconURL> urls;
499 urls.push_back(
500 FaviconURL(icon_url, FaviconURL::FAVICON, std::vector<gfx::Size>()));
501 helper.OnUpdateFaviconURL(0, urls);
503 // Verify FaviconHandler status
504 EXPECT_EQ(1U, helper.urls().size());
505 ASSERT_TRUE(helper.current_candidate());
506 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
507 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
509 // Favicon shouldn't request to download icon.
510 EXPECT_FALSE(helper.download_handler()->HasDownload());
513 TEST_F(FaviconHandlerTest, DownloadFavicon) {
514 const GURL page_url("http://www.google.com");
515 const GURL icon_url("http://www.google.com/favicon");
517 TestFaviconDriver driver;
518 TestFaviconClient client;
519 TestFaviconHandler helper(
520 page_url, &client, &driver, FaviconHandler::FAVICON, false);
522 helper.FetchFavicon(page_url);
523 HistoryRequestHandler* history_handler = helper.history_handler();
524 // Ensure the data given to history is correct.
525 ASSERT_TRUE(history_handler);
526 EXPECT_EQ(page_url, history_handler->page_url_);
527 EXPECT_EQ(GURL(), history_handler->icon_url_);
528 EXPECT_EQ(favicon_base::FAVICON, history_handler->icon_type_);
530 // Set icon data expired
531 SetFaviconBitmapResult(icon_url,
532 favicon_base::FAVICON,
533 true /* expired */,
534 &history_handler->history_results_);
535 // Send history response.
536 history_handler->InvokeCallback();
537 // Verify FaviconHandler status
538 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
539 EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url);
541 // Simulates update favicon url.
542 std::vector<FaviconURL> urls;
543 urls.push_back(
544 FaviconURL(icon_url, FaviconURL::FAVICON, std::vector<gfx::Size>()));
545 helper.OnUpdateFaviconURL(0, urls);
547 // Verify FaviconHandler status
548 EXPECT_EQ(1U, helper.urls().size());
549 ASSERT_TRUE(helper.current_candidate());
550 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
551 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
553 // Favicon should request to download icon now.
554 DownloadHandler* download_handler = helper.download_handler();
555 EXPECT_TRUE(helper.download_handler()->HasDownload());
557 // Verify the download request.
558 EXPECT_EQ(icon_url, download_handler->GetImageUrl());
560 // Reset the history_handler to verify whether favicon is set.
561 helper.set_history_handler(NULL);
563 // Smulates download done.
564 download_handler->InvokeCallback();
566 // New icon should be saved to history backend and navigation entry.
567 history_handler = helper.history_handler();
568 ASSERT_TRUE(history_handler);
569 EXPECT_EQ(icon_url, history_handler->icon_url_);
570 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
571 EXPECT_LT(0U, history_handler->bitmap_data_.size());
572 EXPECT_EQ(page_url, history_handler->page_url_);
574 // Verify NavigationEntry.
575 content::FaviconStatus favicon_status = helper.GetEntry()->GetFavicon();
576 EXPECT_EQ(icon_url, favicon_status.url);
577 EXPECT_TRUE(favicon_status.valid);
578 EXPECT_FALSE(favicon_status.image.IsEmpty());
579 EXPECT_EQ(gfx::kFaviconSize, favicon_status.image.Width());
582 TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) {
583 const GURL page_url("http://www.google.com");
584 const GURL icon_url("http://www.google.com/favicon");
585 const GURL new_icon_url("http://www.google.com/new_favicon");
587 TestFaviconDriver driver;
588 TestFaviconClient client;
589 TestFaviconHandler helper(
590 page_url, &client, &driver, FaviconHandler::FAVICON, false);
592 helper.FetchFavicon(page_url);
593 HistoryRequestHandler* history_handler = helper.history_handler();
594 // Ensure the data given to history is correct.
595 ASSERT_TRUE(history_handler);
596 EXPECT_EQ(page_url, history_handler->page_url_);
597 EXPECT_EQ(GURL(), history_handler->icon_url_);
598 EXPECT_EQ(favicon_base::FAVICON, history_handler->icon_type_);
600 // Set valid icon data.
601 SetFaviconBitmapResult(icon_url, &history_handler->history_results_);
603 // Send history response.
604 history_handler->InvokeCallback();
605 // Verify FaviconHandler status.
606 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
607 EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url);
609 // Reset the history_handler to verify whether new icon is requested from
610 // history.
611 helper.set_history_handler(NULL);
613 // Simulates update with the different favicon url.
614 std::vector<FaviconURL> urls;
615 urls.push_back(
616 FaviconURL(new_icon_url, FaviconURL::FAVICON, std::vector<gfx::Size>()));
617 helper.OnUpdateFaviconURL(0, urls);
619 // Verify FaviconHandler status.
620 EXPECT_EQ(1U, helper.urls().size());
621 ASSERT_TRUE(helper.current_candidate());
622 ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url);
623 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
625 // Favicon should be requested from history.
626 history_handler = helper.history_handler();
627 ASSERT_TRUE(history_handler);
628 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
629 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
630 EXPECT_EQ(page_url, history_handler->page_url_);
632 // Simulate not find icon.
633 history_handler->history_results_.clear();
634 history_handler->InvokeCallback();
636 // Favicon should request to download icon now.
637 DownloadHandler* download_handler = helper.download_handler();
638 EXPECT_TRUE(helper.download_handler()->HasDownload());
640 // Verify the download request.
641 EXPECT_EQ(new_icon_url, download_handler->GetImageUrl());
643 // Reset the history_handler to verify whether favicon is set.
644 helper.set_history_handler(NULL);
646 // Smulates download done.
647 download_handler->InvokeCallback();
649 // New icon should be saved to history backend and navigation entry.
650 history_handler = helper.history_handler();
651 ASSERT_TRUE(history_handler);
652 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
653 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
654 EXPECT_LT(0U, history_handler->bitmap_data_.size());
655 EXPECT_EQ(page_url, history_handler->page_url_);
657 // Verify NavigationEntry.
658 content::FaviconStatus favicon_status = helper.GetEntry()->GetFavicon();
659 EXPECT_EQ(new_icon_url, favicon_status.url);
660 EXPECT_TRUE(favicon_status.valid);
661 EXPECT_FALSE(favicon_status.image.IsEmpty());
662 EXPECT_EQ(gfx::kFaviconSize, favicon_status.image.Width());
665 TEST_F(FaviconHandlerTest, FaviconInHistoryInvalid) {
666 const GURL page_url("http://www.google.com");
667 const GURL icon_url("http://www.google.com/favicon");
669 TestFaviconDriver driver;
670 TestFaviconClient client;
671 TestFaviconHandler helper(
672 page_url, &client, &driver, FaviconHandler::FAVICON, false);
674 helper.FetchFavicon(page_url);
675 HistoryRequestHandler* history_handler = helper.history_handler();
676 // Ensure the data given to history is correct.
677 ASSERT_TRUE(history_handler);
678 EXPECT_EQ(page_url, history_handler->page_url_);
679 EXPECT_EQ(GURL(), history_handler->icon_url_);
680 EXPECT_EQ(favicon_base::FAVICON, history_handler->icon_type_);
682 // Set non empty but invalid data.
683 favicon_base::FaviconBitmapResult bitmap_result;
684 bitmap_result.expired = false;
685 // Empty bitmap data is invalid.
686 bitmap_result.bitmap_data = new base::RefCountedBytes();
687 bitmap_result.pixel_size = gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize);
688 bitmap_result.icon_type = favicon_base::FAVICON;
689 bitmap_result.icon_url = icon_url;
690 history_handler->history_results_.clear();
691 history_handler->history_results_.push_back(bitmap_result);
693 // Send history response.
694 history_handler->InvokeCallback();
695 // The NavigationEntry should not be set yet as the history data is invalid.
696 EXPECT_FALSE(helper.GetEntry()->GetFavicon().valid);
697 EXPECT_EQ(GURL(), helper.GetEntry()->GetFavicon().url);
699 // Reset the history_handler to verify whether new icon is requested from
700 // history.
701 helper.set_history_handler(NULL);
703 // Simulates update with matching favicon URL.
704 std::vector<FaviconURL> urls;
705 urls.push_back(
706 FaviconURL(icon_url, FaviconURL::FAVICON, std::vector<gfx::Size>()));
707 helper.OnUpdateFaviconURL(0, urls);
709 // A download for the favicon should be requested, and we should not do
710 // another history request.
711 DownloadHandler* download_handler = helper.download_handler();
712 EXPECT_TRUE(helper.download_handler()->HasDownload());
713 EXPECT_EQ(NULL, helper.history_handler());
715 // Verify the download request.
716 EXPECT_EQ(icon_url, download_handler->GetImageUrl());
718 // Simulates download done.
719 download_handler->InvokeCallback();
721 // New icon should be saved to history backend and navigation entry.
722 history_handler = helper.history_handler();
723 ASSERT_TRUE(history_handler);
724 EXPECT_EQ(icon_url, history_handler->icon_url_);
725 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
726 EXPECT_LT(0U, history_handler->bitmap_data_.size());
727 EXPECT_EQ(page_url, history_handler->page_url_);
729 // Verify NavigationEntry.
730 content::FaviconStatus favicon_status = helper.GetEntry()->GetFavicon();
731 EXPECT_EQ(icon_url, favicon_status.url);
732 EXPECT_TRUE(favicon_status.valid);
733 EXPECT_FALSE(favicon_status.image.IsEmpty());
734 EXPECT_EQ(gfx::kFaviconSize, favicon_status.image.Width());
737 TEST_F(FaviconHandlerTest, UpdateFavicon) {
738 const GURL page_url("http://www.google.com");
739 const GURL icon_url("http://www.google.com/favicon");
740 const GURL new_icon_url("http://www.google.com/new_favicon");
742 TestFaviconDriver driver;
743 TestFaviconClient client;
744 TestFaviconHandler helper(
745 page_url, &client, &driver, FaviconHandler::FAVICON, false);
747 helper.FetchFavicon(page_url);
748 HistoryRequestHandler* history_handler = helper.history_handler();
749 // Ensure the data given to history is correct.
750 ASSERT_TRUE(history_handler);
751 EXPECT_EQ(page_url, history_handler->page_url_);
752 EXPECT_EQ(GURL(), history_handler->icon_url_);
753 EXPECT_EQ(favicon_base::FAVICON, history_handler->icon_type_);
755 SetFaviconBitmapResult(icon_url, &history_handler->history_results_);
757 // Send history response.
758 history_handler->InvokeCallback();
759 // Verify FaviconHandler status.
760 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
761 EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url);
763 // Reset the history_handler to verify whether new icon is requested from
764 // history.
765 helper.set_history_handler(NULL);
767 // Simulates update with the different favicon url.
768 std::vector<FaviconURL> urls;
769 urls.push_back(
770 FaviconURL(new_icon_url, FaviconURL::FAVICON, std::vector<gfx::Size>()));
771 helper.OnUpdateFaviconURL(0, urls);
773 // Verify FaviconHandler status.
774 EXPECT_EQ(1U, helper.urls().size());
775 ASSERT_TRUE(helper.current_candidate());
776 ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url);
777 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
779 // Favicon should be requested from history.
780 history_handler = helper.history_handler();
781 ASSERT_TRUE(history_handler);
782 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
783 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
784 EXPECT_EQ(page_url, history_handler->page_url_);
786 // Simulate find icon.
787 SetFaviconBitmapResult(new_icon_url, &history_handler->history_results_);
788 history_handler->InvokeCallback();
790 // Shouldn't request download favicon
791 EXPECT_FALSE(helper.download_handler()->HasDownload());
793 // Verify the favicon status.
794 EXPECT_EQ(new_icon_url, helper.GetEntry()->GetFavicon().url);
795 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
796 EXPECT_FALSE(helper.GetEntry()->GetFavicon().image.IsEmpty());
799 TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) {
800 const GURL page_url("http://www.google.com");
801 const GURL icon_url("http://www.google.com/favicon");
802 const GURL new_icon_url("http://www.google.com/new_favicon");
804 TestFaviconDriver driver;
805 TestFaviconClient client;
806 TestFaviconHandler helper(
807 page_url, &client, &driver, FaviconHandler::TOUCH, false);
809 helper.FetchFavicon(page_url);
810 HistoryRequestHandler* history_handler = helper.history_handler();
811 // Ensure the data given to history is correct.
812 ASSERT_TRUE(history_handler);
813 EXPECT_EQ(page_url, history_handler->page_url_);
814 EXPECT_EQ(GURL(), history_handler->icon_url_);
815 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON | favicon_base::TOUCH_ICON,
816 history_handler->icon_type_);
818 // Icon not found.
819 history_handler->history_results_.clear();
820 // Send history response.
821 history_handler->InvokeCallback();
822 // Verify FaviconHandler status.
823 EXPECT_FALSE(helper.GetEntry()->GetFavicon().valid);
824 EXPECT_EQ(GURL(), helper.GetEntry()->GetFavicon().url);
826 // Reset the history_handler to verify whether new icon is requested from
827 // history.
828 helper.set_history_handler(NULL);
830 // Simulates update with the different favicon url.
831 std::vector<FaviconURL> urls;
832 urls.push_back(FaviconURL(
833 icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON, std::vector<gfx::Size>()));
834 urls.push_back(FaviconURL(
835 new_icon_url, FaviconURL::TOUCH_ICON, std::vector<gfx::Size>()));
836 urls.push_back(
837 FaviconURL(new_icon_url, FaviconURL::FAVICON, std::vector<gfx::Size>()));
838 helper.OnUpdateFaviconURL(0, urls);
840 // Verify FaviconHandler status.
841 EXPECT_EQ(2U, helper.urls().size());
842 ASSERT_TRUE(helper.current_candidate());
843 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
844 ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON,
845 helper.current_candidate()->icon_type);
847 // Favicon should be requested from history.
848 history_handler = helper.history_handler();
849 ASSERT_TRUE(history_handler);
850 EXPECT_EQ(icon_url, history_handler->icon_url_);
851 EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_);
852 EXPECT_EQ(page_url, history_handler->page_url_);
854 // Simulate not find icon.
855 history_handler->history_results_.clear();
856 history_handler->InvokeCallback();
858 // Should request download favicon.
859 DownloadHandler* download_handler = helper.download_handler();
860 EXPECT_TRUE(helper.download_handler()->HasDownload());
862 // Verify the download request.
863 EXPECT_EQ(icon_url, download_handler->GetImageUrl());
865 // Reset the history_handler to verify whether favicon is request from
866 // history.
867 helper.set_history_handler(NULL);
868 // Smulates download failed.
869 download_handler->set_failed(true);
870 download_handler->InvokeCallback();
872 // Left 1 url.
873 EXPECT_EQ(1U, helper.urls().size());
874 ASSERT_TRUE(helper.current_candidate());
875 EXPECT_EQ(new_icon_url, helper.current_candidate()->icon_url);
876 EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type);
878 // Favicon should be requested from history.
879 history_handler = helper.history_handler();
880 ASSERT_TRUE(history_handler);
881 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
882 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
883 EXPECT_EQ(page_url, history_handler->page_url_);
885 // Reset download handler
886 download_handler->Reset();
888 // Simulates getting a expired icon from history.
889 SetFaviconBitmapResult(new_icon_url,
890 favicon_base::TOUCH_ICON,
891 true /* expired */,
892 &history_handler->history_results_);
893 history_handler->InvokeCallback();
895 // Verify the download request.
896 EXPECT_TRUE(helper.download_handler()->HasDownload());
897 EXPECT_EQ(new_icon_url, download_handler->GetImageUrl());
899 helper.set_history_handler(NULL);
901 // Simulates icon being downloaded.
902 download_handler->InvokeCallback();
904 // New icon should be saved to history backend.
905 history_handler = helper.history_handler();
906 ASSERT_TRUE(history_handler);
907 EXPECT_EQ(new_icon_url, history_handler->icon_url_);
908 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
909 EXPECT_LT(0U, history_handler->bitmap_data_.size());
910 EXPECT_EQ(page_url, history_handler->page_url_);
913 TEST_F(FaviconHandlerTest, UpdateDuringDownloading) {
914 const GURL page_url("http://www.google.com");
915 const GURL icon_url("http://www.google.com/favicon");
916 const GURL new_icon_url("http://www.google.com/new_favicon");
918 TestFaviconDriver driver;
919 TestFaviconClient client;
920 TestFaviconHandler helper(
921 page_url, &client, &driver, FaviconHandler::TOUCH, false);
923 helper.FetchFavicon(page_url);
924 HistoryRequestHandler* history_handler = helper.history_handler();
925 // Ensure the data given to history is correct.
926 ASSERT_TRUE(history_handler);
927 EXPECT_EQ(page_url, history_handler->page_url_);
928 EXPECT_EQ(GURL(), history_handler->icon_url_);
929 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON | favicon_base::TOUCH_ICON,
930 history_handler->icon_type_);
932 // Icon not found.
933 history_handler->history_results_.clear();
934 // Send history response.
935 history_handler->InvokeCallback();
936 // Verify FaviconHandler status.
937 EXPECT_FALSE(helper.GetEntry()->GetFavicon().valid);
938 EXPECT_EQ(GURL(), helper.GetEntry()->GetFavicon().url);
940 // Reset the history_handler to verify whether new icon is requested from
941 // history.
942 helper.set_history_handler(NULL);
944 // Simulates update with the different favicon url.
945 std::vector<FaviconURL> urls;
946 urls.push_back(FaviconURL(
947 icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON, std::vector<gfx::Size>()));
948 urls.push_back(FaviconURL(
949 new_icon_url, FaviconURL::TOUCH_ICON, std::vector<gfx::Size>()));
950 urls.push_back(
951 FaviconURL(new_icon_url, FaviconURL::FAVICON, std::vector<gfx::Size>()));
952 helper.OnUpdateFaviconURL(0, urls);
954 // Verify FaviconHandler status.
955 EXPECT_EQ(2U, helper.urls().size());
956 ASSERT_TRUE(helper.current_candidate());
957 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
958 ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON,
959 helper.current_candidate()->icon_type);
961 // Favicon should be requested from history.
962 history_handler = helper.history_handler();
963 ASSERT_TRUE(history_handler);
964 EXPECT_EQ(icon_url, history_handler->icon_url_);
965 EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_);
966 EXPECT_EQ(page_url, history_handler->page_url_);
968 // Simulate not find icon.
969 history_handler->history_results_.clear();
970 history_handler->InvokeCallback();
972 // Should request download favicon.
973 DownloadHandler* download_handler = helper.download_handler();
974 EXPECT_TRUE(helper.download_handler()->HasDownload());
976 // Verify the download request.
977 EXPECT_EQ(icon_url, download_handler->GetImageUrl());
979 // Reset the history_handler to verify whether favicon is request from
980 // history.
981 helper.set_history_handler(NULL);
982 const GURL latest_icon_url("http://www.google.com/latest_favicon");
983 std::vector<FaviconURL> latest_urls;
984 latest_urls.push_back(FaviconURL(
985 latest_icon_url, FaviconURL::TOUCH_ICON, std::vector<gfx::Size>()));
986 helper.OnUpdateFaviconURL(0, latest_urls);
988 EXPECT_EQ(1U, helper.urls().size());
989 EXPECT_EQ(latest_icon_url, helper.current_candidate()->icon_url);
990 EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type);
992 // Whether new icon is requested from history
993 history_handler = helper.history_handler();
994 ASSERT_TRUE(history_handler);
995 EXPECT_EQ(latest_icon_url, history_handler->icon_url_);
996 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
997 EXPECT_EQ(page_url, history_handler->page_url_);
999 // Reset the history_handler to verify whether favicon is request from
1000 // history.
1001 // Save the callback for late use.
1002 FaviconService::FaviconResultsCallback callback = history_handler->callback_;
1003 helper.set_history_handler(NULL);
1005 // Simulates download succeed.
1006 download_handler->InvokeCallback();
1007 // The downloaded icon should be thrown away as there is favicon update.
1008 EXPECT_FALSE(helper.history_handler());
1010 download_handler->Reset();
1012 // Simulates getting the icon from history.
1013 scoped_ptr<HistoryRequestHandler> handler;
1014 handler.reset(new HistoryRequestHandler(
1015 page_url, latest_icon_url, favicon_base::TOUCH_ICON, callback));
1016 SetFaviconBitmapResult(latest_icon_url,
1017 favicon_base::TOUCH_ICON,
1018 false /* expired */,
1019 &handler->history_results_);
1020 handler->InvokeCallback();
1022 // No download request.
1023 EXPECT_FALSE(download_handler->HasDownload());
1026 #if !defined(OS_ANDROID)
1028 // Test the favicon which is selected when the web page provides several
1029 // favicons and none of the favicons are cached in history.
1030 // The goal of this test is to be more of an integration test than
1031 // SelectFaviconFramesTest.*.
1032 TEST_F(FaviconHandlerTest, MultipleFavicons) {
1033 const GURL kPageURL("http://www.google.com");
1034 const FaviconURL kSourceIconURLs[] = {
1035 FaviconURL(GURL("http://www.google.com/a"),
1036 FaviconURL::FAVICON,
1037 std::vector<gfx::Size>()),
1038 FaviconURL(GURL("http://www.google.com/b"),
1039 FaviconURL::FAVICON,
1040 std::vector<gfx::Size>()),
1041 FaviconURL(GURL("http://www.google.com/c"),
1042 FaviconURL::FAVICON,
1043 std::vector<gfx::Size>()),
1044 FaviconURL(GURL("http://www.google.com/d"),
1045 FaviconURL::FAVICON,
1046 std::vector<gfx::Size>()),
1047 FaviconURL(GURL("http://www.google.com/e"),
1048 FaviconURL::FAVICON,
1049 std::vector<gfx::Size>())};
1051 // Set the supported scale factors to 1x and 2x. This affects the behavior of
1052 // SelectFaviconFrames().
1053 std::vector<ui::ScaleFactor> scale_factors;
1054 scale_factors.push_back(ui::SCALE_FACTOR_100P);
1055 scale_factors.push_back(ui::SCALE_FACTOR_200P);
1056 ui::test::ScopedSetSupportedScaleFactors scoped_supported(scale_factors);
1058 // 1) Test that if there are several single resolution favicons to choose from
1059 // that the largest exact match is chosen.
1060 TestFaviconDriver driver1;
1061 TestFaviconClient client;
1062 TestFaviconHandler handler1(
1063 kPageURL, &client, &driver1, FaviconHandler::FAVICON, false);
1065 const int kSizes1[] = { 16, 24, 32, 48, 256 };
1066 std::vector<FaviconURL> urls1(kSourceIconURLs,
1067 kSourceIconURLs + arraysize(kSizes1));
1068 DownloadTillDoneIgnoringHistory(&handler1, kPageURL, urls1, kSizes1);
1070 content::FaviconStatus favicon_status1(handler1.GetEntry()->GetFavicon());
1071 EXPECT_EQ(0u, handler1.image_urls().size());
1072 EXPECT_TRUE(favicon_status1.valid);
1073 EXPECT_FALSE(favicon_status1.image.IsEmpty());
1074 EXPECT_EQ(gfx::kFaviconSize, favicon_status1.image.Width());
1076 size_t expected_index = 2u;
1077 EXPECT_EQ(32, kSizes1[expected_index]);
1078 EXPECT_EQ(kSourceIconURLs[expected_index].icon_url,
1079 handler1.GetEntry()->GetFavicon().url);
1081 // 2) Test that if there are several single resolution favicons to choose
1082 // from, the exact match is preferred even if it results in upsampling.
1083 TestFaviconDriver driver2;
1084 TestFaviconHandler handler2(
1085 kPageURL, &client, &driver2, FaviconHandler::FAVICON, false);
1087 const int kSizes2[] = { 16, 24, 48, 256 };
1088 std::vector<FaviconURL> urls2(kSourceIconURLs,
1089 kSourceIconURLs + arraysize(kSizes2));
1090 DownloadTillDoneIgnoringHistory(&handler2, kPageURL, urls2, kSizes2);
1091 EXPECT_TRUE(handler2.GetEntry()->GetFavicon().valid);
1092 expected_index = 0u;
1093 EXPECT_EQ(16, kSizes2[expected_index]);
1094 EXPECT_EQ(kSourceIconURLs[expected_index].icon_url,
1095 handler2.GetEntry()->GetFavicon().url);
1097 // 3) Test that favicons which need to be upsampled a little or downsampled
1098 // a little are preferred over huge favicons.
1099 TestFaviconDriver driver3;
1100 TestFaviconHandler handler3(
1101 kPageURL, &client, &driver3, FaviconHandler::FAVICON, false);
1103 const int kSizes3[] = { 256, 48 };
1104 std::vector<FaviconURL> urls3(kSourceIconURLs,
1105 kSourceIconURLs + arraysize(kSizes3));
1106 DownloadTillDoneIgnoringHistory(&handler3, kPageURL, urls3, kSizes3);
1107 EXPECT_TRUE(handler3.GetEntry()->GetFavicon().valid);
1108 expected_index = 1u;
1109 EXPECT_EQ(48, kSizes3[expected_index]);
1110 EXPECT_EQ(kSourceIconURLs[expected_index].icon_url,
1111 handler3.GetEntry()->GetFavicon().url);
1113 TestFaviconDriver driver4;
1114 TestFaviconHandler handler4(
1115 kPageURL, &client, &driver4, FaviconHandler::FAVICON, false);
1117 const int kSizes4[] = { 17, 256 };
1118 std::vector<FaviconURL> urls4(kSourceIconURLs,
1119 kSourceIconURLs + arraysize(kSizes4));
1120 DownloadTillDoneIgnoringHistory(&handler4, kPageURL, urls4, kSizes4);
1121 EXPECT_TRUE(handler4.GetEntry()->GetFavicon().valid);
1122 expected_index = 0u;
1123 EXPECT_EQ(17, kSizes4[expected_index]);
1124 EXPECT_EQ(kSourceIconURLs[expected_index].icon_url,
1125 handler4.GetEntry()->GetFavicon().url);
1128 #endif
1130 TEST_F(FaviconHandlerTest, TestSortFavicon) {
1131 const GURL kPageURL("http://www.google.com");
1132 std::vector<gfx::Size> icon1;
1133 icon1.push_back(gfx::Size(1024, 1024));
1134 icon1.push_back(gfx::Size(512, 512));
1136 std::vector<gfx::Size> icon2;
1137 icon2.push_back(gfx::Size(15, 15));
1138 icon2.push_back(gfx::Size(16, 16));
1140 std::vector<gfx::Size> icon3;
1141 icon3.push_back(gfx::Size(16, 16));
1142 icon3.push_back(gfx::Size(14, 14));
1144 const FaviconURL kSourceIconURLs[] = {
1145 FaviconURL(GURL("http://www.google.com/a"),
1146 FaviconURL::FAVICON,
1147 icon1),
1148 FaviconURL(GURL("http://www.google.com/b"),
1149 FaviconURL::FAVICON,
1150 icon2),
1151 FaviconURL(GURL("http://www.google.com/c"),
1152 FaviconURL::FAVICON,
1153 icon3),
1154 FaviconURL(GURL("http://www.google.com/d"),
1155 FaviconURL::FAVICON,
1156 std::vector<gfx::Size>()),
1157 FaviconURL(GURL("http://www.google.com/e"),
1158 FaviconURL::FAVICON,
1159 std::vector<gfx::Size>())};
1161 TestFaviconClient client;
1162 TestFaviconDriver driver1;
1163 TestFaviconHandler handler1(
1164 kPageURL, &client, &driver1, FaviconHandler::FAVICON, true);
1165 std::vector<FaviconURL> urls1(kSourceIconURLs,
1166 kSourceIconURLs + arraysize(kSourceIconURLs));
1167 UpdateFaviconURL(&handler1, kPageURL, urls1);
1169 struct ExpectedResult {
1170 // The favicon's index in kSourceIconURLs.
1171 size_t favicon_index;
1172 // Width of largest bitmap.
1173 int width;
1174 } results[] = {
1175 // First is icon1
1176 // The 16x16 is largest.
1177 {1, 16},
1178 // Second is iocn2 though it has same size as icon1.
1179 // The 16x16 is largest.
1180 {2, 16},
1181 // The rest of bitmaps come in order, there is no sizes attribute.
1182 {3, -1},
1183 {4, -1},
1185 const std::vector<FaviconURL>& icons = handler1.image_urls();
1186 ASSERT_EQ(4u, icons.size());
1187 for (size_t i = 0; i < 4; ++i) {
1188 EXPECT_EQ(kSourceIconURLs[results[i].favicon_index].icon_url,
1189 icons[i].icon_url);
1190 if (results[i].width != -1)
1191 EXPECT_EQ(results[i].width, icons[i].icon_sizes[0].width());
1195 TEST_F(FaviconHandlerTest, TestDownloadLargestFavicon) {
1196 const GURL kPageURL("http://www.google.com");
1197 std::vector<gfx::Size> too_large;
1198 too_large.push_back(gfx::Size(1024, 1024));
1199 too_large.push_back(gfx::Size(512, 512));
1201 std::vector<gfx::Size> one_icon;
1202 one_icon.push_back(gfx::Size(15, 15));
1203 one_icon.push_back(gfx::Size(512, 512));
1205 std::vector<gfx::Size> two_icons;
1206 two_icons.push_back(gfx::Size(16, 16));
1207 two_icons.push_back(gfx::Size(14, 14));
1209 const FaviconURL kSourceIconURLs[] = {
1210 FaviconURL(GURL("http://www.google.com/a"),
1211 FaviconURL::FAVICON,
1212 too_large),
1213 FaviconURL(GURL("http://www.google.com/b"),
1214 FaviconURL::FAVICON,
1215 one_icon),
1216 FaviconURL(GURL("http://www.google.com/c"),
1217 FaviconURL::FAVICON,
1218 two_icons),
1219 FaviconURL(GURL("http://www.google.com/d"),
1220 FaviconURL::FAVICON,
1221 std::vector<gfx::Size>()),
1222 FaviconURL(GURL("http://www.google.com/e"),
1223 FaviconURL::FAVICON,
1224 std::vector<gfx::Size>())};
1226 TestFaviconClient client;
1227 TestFaviconDriver driver1;
1228 TestFaviconHandler handler1(
1229 kPageURL, &client, &driver1, FaviconHandler::FAVICON, true);
1230 std::vector<FaviconURL> urls1(kSourceIconURLs,
1231 kSourceIconURLs + arraysize(kSourceIconURLs));
1232 UpdateFaviconURL(&handler1, kPageURL, urls1);
1234 // Simulate the download failed, to check whether the icons were requested
1235 // to download according their size.
1236 struct ExpectedResult {
1237 // The size of image_urls_.
1238 size_t image_urls_size;
1239 // The favicon's index in kSourceIconURLs.
1240 size_t favicon_index;
1241 // Width of largest bitmap.
1242 int width;
1243 } results[] = {
1244 // The 1024x1024 and 512x512 icons were dropped as it excceeds maximal size,
1245 // image_urls_ is 4 elements.
1246 // The 16x16 is largest.
1247 {4, 2, 16},
1248 // The 16x16 was dropped.
1249 // The 15x15 is largest.
1250 {3, 1, 15},
1251 // The rest of bitmaps come in order.
1252 {2, 3, -1},
1253 {1, 4, -1},
1256 for (int i = 0; i < 4; ++i) {
1257 ASSERT_EQ(results[i].image_urls_size, handler1.image_urls().size());
1258 EXPECT_EQ(kSourceIconURLs[results[i].favicon_index].icon_url,
1259 handler1.current_candidate()->icon_url);
1260 if (results[i].width != -1) {
1261 EXPECT_EQ(results[i].width, handler1.current_candidate()->
1262 icon_sizes[0].width());
1265 // Simulate no favicon from history.
1266 handler1.history_handler()->history_results_.clear();
1267 handler1.history_handler()->InvokeCallback();
1269 // Verify download request
1270 ASSERT_TRUE(handler1.download_handler()->HasDownload());
1271 EXPECT_EQ(kSourceIconURLs[results[i].favicon_index].icon_url,
1272 handler1.download_handler()->GetImageUrl());
1274 // Simulate the download failed.
1275 handler1.download_handler()->set_failed(true);
1276 handler1.download_handler()->InvokeCallback();
1280 TEST_F(FaviconHandlerTest, TestSelectLargestFavicon) {
1281 const GURL kPageURL("http://www.google.com");
1283 std::vector<gfx::Size> one_icon;
1284 one_icon.push_back(gfx::Size(15, 15));
1286 std::vector<gfx::Size> two_icons;
1287 two_icons.push_back(gfx::Size(14, 14));
1288 two_icons.push_back(gfx::Size(16, 16));
1290 const FaviconURL kSourceIconURLs[] = {
1291 FaviconURL(GURL("http://www.google.com/b"),
1292 FaviconURL::FAVICON,
1293 one_icon),
1294 FaviconURL(GURL("http://www.google.com/c"),
1295 FaviconURL::FAVICON,
1296 two_icons)};
1298 TestFaviconClient client;
1299 TestFaviconDriver driver1;
1300 TestFaviconHandler handler1(
1301 kPageURL, &client, &driver1, FaviconHandler::FAVICON, true);
1302 std::vector<FaviconURL> urls1(kSourceIconURLs,
1303 kSourceIconURLs + arraysize(kSourceIconURLs));
1304 UpdateFaviconURL(&handler1, kPageURL, urls1);
1306 ASSERT_EQ(2u, handler1.urls().size());
1308 // Index of largest favicon in kSourceIconURLs.
1309 size_t i = 1;
1310 // The largest bitmap's index in Favicon .
1311 int b = 1;
1313 // Verify the icon_bitmaps_ was initialized correctly.
1314 EXPECT_EQ(kSourceIconURLs[i].icon_url,
1315 handler1.current_candidate()->icon_url);
1316 EXPECT_EQ(kSourceIconURLs[i].icon_sizes[b],
1317 handler1.current_candidate()->icon_sizes[0]);
1319 // Simulate no favicon from history.
1320 handler1.history_handler()->history_results_.clear();
1321 handler1.history_handler()->InvokeCallback();
1323 // Verify download request
1324 ASSERT_TRUE(handler1.download_handler()->HasDownload());
1325 EXPECT_EQ(kSourceIconURLs[i].icon_url,
1326 handler1.download_handler()->GetImageUrl());
1328 // Give the correct download result.
1329 std::vector<int> sizes;
1330 for (std::vector<gfx::Size>::const_iterator j =
1331 kSourceIconURLs[i].icon_sizes.begin();
1332 j != kSourceIconURLs[i].icon_sizes.end(); ++j)
1333 sizes.push_back(j->width());
1335 handler1.download_handler()->SetImageSizes(sizes);
1336 handler1.download_handler()->InvokeCallback();
1338 // Verify the largest bitmap has been saved into history.
1339 EXPECT_EQ(kSourceIconURLs[i].icon_url, handler1.history_handler()->icon_url_);
1340 EXPECT_EQ(kSourceIconURLs[i].icon_sizes[b],
1341 handler1.history_handler()->size_);
1344 TEST_F(FaviconHandlerTest, TestKeepDownloadedLargestFavicon) {
1345 const GURL kPageURL("http://www.google.com");
1347 std::vector<gfx::Size> icon1;
1348 icon1.push_back(gfx::Size(16, 16));
1349 const int actual_size1 = 10;
1351 std::vector<gfx::Size> icon2;
1352 icon2.push_back(gfx::Size(15, 15));
1353 const int actual_size2 = 12;
1355 const FaviconURL kSourceIconURLs[] = {
1356 FaviconURL(GURL("http://www.google.com/b"),
1357 FaviconURL::FAVICON,
1358 icon1),
1359 FaviconURL(GURL("http://www.google.com/c"),
1360 FaviconURL::FAVICON,
1361 icon2),
1362 FaviconURL(GURL("http://www.google.com/d"),
1363 FaviconURL::FAVICON,
1364 std::vector<gfx::Size>())};
1366 TestFaviconClient client;
1367 TestFaviconDriver driver1;
1368 TestFaviconHandler handler1(
1369 kPageURL, &client, &driver1, FaviconHandler::FAVICON, true);
1370 std::vector<FaviconURL> urls1(kSourceIconURLs,
1371 kSourceIconURLs + arraysize(kSourceIconURLs));
1372 UpdateFaviconURL(&handler1, kPageURL, urls1);
1373 ASSERT_EQ(3u, handler1.urls().size());
1375 // Simulate no favicon from history.
1376 handler1.history_handler()->history_results_.clear();
1377 handler1.history_handler()->InvokeCallback();
1379 // Verify the first icon was request to download
1380 ASSERT_TRUE(handler1.download_handler()->HasDownload());
1381 EXPECT_EQ(kSourceIconURLs[0].icon_url,
1382 handler1.download_handler()->GetImageUrl());
1384 // Give the incorrect size.
1385 std::vector<int> sizes;
1386 sizes.push_back(actual_size1);
1387 handler1.download_handler()->SetImageSizes(sizes);
1388 handler1.download_handler()->InvokeCallback();
1390 // Simulate no favicon from history.
1391 handler1.history_handler()->history_results_.clear();
1392 handler1.history_handler()->InvokeCallback();
1394 // Verify the 2nd icon was request to download
1395 ASSERT_TRUE(handler1.download_handler()->HasDownload());
1396 EXPECT_EQ(kSourceIconURLs[1].icon_url,
1397 handler1.download_handler()->GetImageUrl());
1399 // Very the best candidate is icon1
1400 EXPECT_EQ(kSourceIconURLs[0].icon_url,
1401 handler1.best_favicon_candidate().image_url);
1402 EXPECT_EQ(gfx::Size(actual_size1, actual_size1),
1403 handler1.best_favicon_candidate().image.Size());
1405 // Give the incorrect size.
1406 sizes.clear();
1407 sizes.push_back(actual_size2);
1408 handler1.download_handler()->SetImageSizes(sizes);
1409 handler1.download_handler()->InvokeCallback();
1411 // Verify icon2 has been saved into history.
1412 EXPECT_EQ(kSourceIconURLs[1].icon_url, handler1.history_handler()->icon_url_);
1413 EXPECT_EQ(gfx::Size(actual_size2, actual_size2),
1414 handler1.history_handler()->size_);
1417 static KeyedService* BuildFaviconService(content::BrowserContext* profile) {
1418 return new FaviconService(static_cast<Profile*>(profile));
1421 static KeyedService* BuildHistoryService(content::BrowserContext* profile) {
1422 return NULL;
1425 // Test that Favicon is not requested repeatedly during the same session if
1426 // server returns HTTP 404 status.
1427 TEST_F(FaviconHandlerTest, UnableToDownloadFavicon) {
1428 const GURL missing_icon_url("http://www.google.com/favicon.ico");
1429 const GURL another_icon_url("http://www.youtube.com/favicon.ico");
1431 Profile* profile = Profile::FromBrowserContext(
1432 web_contents()->GetBrowserContext());
1434 FaviconServiceFactory::GetInstance()->SetTestingFactory(
1435 profile, BuildFaviconService);
1437 HistoryServiceFactory::GetInstance()->SetTestingFactory(
1438 profile, BuildHistoryService);
1440 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
1441 profile, Profile::IMPLICIT_ACCESS);
1443 FaviconTabHelper::CreateForWebContents(web_contents());
1444 FaviconTabHelper* favicon_tab_helper =
1445 FaviconTabHelper::FromWebContents(web_contents());
1447 std::vector<SkBitmap> empty_icons;
1448 std::vector<gfx::Size> empty_icon_sizes;
1449 int download_id = 0;
1451 // Try to download missing icon.
1452 download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
1453 EXPECT_NE(0, download_id);
1454 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
1456 // Report download failure with HTTP 503 status.
1457 favicon_tab_helper->DidDownloadFavicon(download_id, 503, missing_icon_url,
1458 empty_icons, empty_icon_sizes);
1459 // Icon is not marked as UnableToDownload as HTTP status is not 404.
1460 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
1462 // Try to download again.
1463 download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
1464 EXPECT_NE(0, download_id);
1465 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
1467 // Report download failure with HTTP 404 status.
1468 favicon_tab_helper->DidDownloadFavicon(download_id, 404, missing_icon_url,
1469 empty_icons, empty_icon_sizes);
1470 // Icon is marked as UnableToDownload.
1471 EXPECT_TRUE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
1473 // Try to download again.
1474 download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
1475 // Download is not started and Icon is still marked as UnableToDownload.
1476 EXPECT_EQ(0, download_id);
1477 EXPECT_TRUE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
1479 // Try to download another icon.
1480 download_id = favicon_tab_helper->StartDownload(another_icon_url, 0);
1481 // Download is started as another icon URL is not same as missing_icon_url.
1482 EXPECT_NE(0, download_id);
1483 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(another_icon_url));
1485 // Clear the list of missing icons.
1486 favicon_service->ClearUnableToDownloadFavicons();
1487 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
1488 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(another_icon_url));
1490 // Try to download again.
1491 download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
1492 EXPECT_NE(0, download_id);
1493 // Report download success with HTTP 200 status.
1494 favicon_tab_helper->DidDownloadFavicon(download_id, 200, missing_icon_url,
1495 empty_icons, empty_icon_sizes);
1496 // Icon is not marked as UnableToDownload as HTTP status is not 404.
1497 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
1500 } // namespace.