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
;
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
);
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
) {
46 FillDataToBitmap(w
, h
, &bitmap
);
47 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap
, false, output
);
50 void SetFaviconBitmapResult(
52 favicon_base::IconType icon_type
,
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(
70 std::vector
<favicon_base::FaviconBitmapResult
>* favicon_bitmap_results
) {
71 SetFaviconBitmapResult(icon_url
,
72 favicon_base::FAVICON
,
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
{
81 explicit DownloadHandler(TestFaviconHandler
* favicon_helper
)
82 : favicon_helper_(favicon_helper
),
86 virtual ~DownloadHandler() {
90 download_
.reset(NULL
);
96 const GURL
& image_url
,
97 const std::vector
<int>& image_sizes
,
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
; }
116 const std::vector
<int>& sizes
,
122 max_image_size(max_size
) {}
126 std::vector
<int> image_sizes
;
130 TestFaviconHandler
* favicon_helper_
;
131 scoped_ptr
<Download
> download_
;
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
{
141 HistoryRequestHandler(const GURL
& page_url
,
142 const GURL
& icon_url
,
144 const FaviconService::FaviconResultsCallback
& callback
)
145 : page_url_(page_url
),
147 icon_type_(icon_type
),
148 callback_(callback
) {
151 HistoryRequestHandler(const GURL
& page_url
,
152 const GURL
& icon_url
,
154 const std::vector
<unsigned char>& bitmap_data
,
155 const gfx::Size
& size
)
156 : page_url_(page_url
),
158 icon_type_(icon_type
),
159 bitmap_data_(bitmap_data
),
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_
;
175 DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler
);
180 class TestFaviconClient
: public FaviconClient
{
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
{
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.";
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.";
215 virtual void NotifyFaviconUpdated(bool icon_url_changed
) OVERRIDE
{
216 ADD_FAILURE() << "TestFaviconDriver::NotifyFaviconUpdated() "
217 << "should never be called in tests.";
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
227 class TestFaviconHandler
: public FaviconHandler
{
229 TestFaviconHandler(const GURL
& page_url
,
230 FaviconClient
* client
,
231 FaviconDriver
* driver
,
233 bool download_largest_icon
)
234 : FaviconHandler(client
, driver
, type
,
235 download_largest_icon
),
236 entry_(NavigationEntry::Create()),
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
{
272 const std::vector
<FaviconURL
>& urls() {
276 FaviconURL
* current_candidate() {
277 return FaviconHandler::current_candidate();
280 const FaviconCandidate
& best_favicon_candidate() {
281 return best_favicon_candidate_
;
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
,
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
{
316 std::vector
<int> sizes
;
318 download_handler_
->AddDownload(
319 download_id_
, image_url
, sizes
, max_bitmap_size
);
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
{
338 virtual void NotifyFaviconUpdated(bool icon_url_changed
) OVERRIDE
{
339 ++num_favicon_updates_
;
345 scoped_ptr
<NavigationEntry
> entry_
;
347 // The unique id of a download request. It will be returned to a
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
);
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
;
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
;
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
,
389 original_bitmap_sizes
);
392 class FaviconHandlerTest
: public ChromeRenderViewHostTestHarness
{
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())
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(
462 ChromeRenderViewHostTestHarness::TearDown();
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
;
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
,
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
;
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
611 helper
.set_history_handler(NULL
);
613 // Simulates update with the different favicon url.
614 std::vector
<FaviconURL
> urls
;
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
701 helper
.set_history_handler(NULL
);
703 // Simulates update with matching favicon URL.
704 std::vector
<FaviconURL
> urls
;
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
765 helper
.set_history_handler(NULL
);
767 // Simulates update with the different favicon url.
768 std::vector
<FaviconURL
> urls
;
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_
);
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
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
>()));
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
867 helper
.set_history_handler(NULL
);
868 // Smulates download failed.
869 download_handler
->set_failed(true);
870 download_handler
->InvokeCallback();
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
,
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_
);
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
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
>()));
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
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
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
);
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
,
1148 FaviconURL(GURL("http://www.google.com/b"),
1149 FaviconURL::FAVICON
,
1151 FaviconURL(GURL("http://www.google.com/c"),
1152 FaviconURL::FAVICON
,
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.
1176 // The 16x16 is largest.
1178 // Second is iocn2 though it has same size as icon1.
1179 // The 16x16 is largest.
1181 // The rest of bitmaps come in order, there is no sizes attribute.
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
,
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
,
1213 FaviconURL(GURL("http://www.google.com/b"),
1214 FaviconURL::FAVICON
,
1216 FaviconURL(GURL("http://www.google.com/c"),
1217 FaviconURL::FAVICON
,
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.
1244 // The 1024x1024 and 512x512 icons were dropped as it excceeds maximal size,
1245 // image_urls_ is 4 elements.
1246 // The 16x16 is largest.
1248 // The 16x16 was dropped.
1249 // The 15x15 is largest.
1251 // The rest of bitmaps come in order.
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
,
1294 FaviconURL(GURL("http://www.google.com/c"),
1295 FaviconURL::FAVICON
,
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.
1310 // The largest bitmap's index in Favicon .
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
,
1359 FaviconURL(GURL("http://www.google.com/c"),
1360 FaviconURL::FAVICON
,
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.
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
) {
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
));