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 "chrome/browser/favicon/favicon_handler.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "chrome/browser/favicon/chrome_favicon_client.h"
9 #include "chrome/browser/favicon/chrome_favicon_client_factory.h"
10 #include "chrome/browser/favicon/favicon_service.h"
11 #include "chrome/browser/favicon/favicon_service_factory.h"
12 #include "chrome/browser/favicon/favicon_tab_helper.h"
13 #include "chrome/browser/history/history_service_factory.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
16 #include "third_party/skia/include/core/SkBitmap.h"
17 #include "ui/gfx/codec/png_codec.h"
18 #include "ui/gfx/favicon_size.h"
19 #include "ui/gfx/image/image.h"
21 class TestFaviconHandler
;
23 using favicon::FaviconURL
;
27 // Fill the given bmp with valid png data.
28 void FillDataToBitmap(int w
, int h
, SkBitmap
* bmp
) {
29 bmp
->allocN32Pixels(w
, h
);
31 unsigned char* src_data
=
32 reinterpret_cast<unsigned char*>(bmp
->getAddr32(0, 0));
33 for (int i
= 0; i
< w
* h
; i
++) {
34 src_data
[i
* 4 + 0] = static_cast<unsigned char>(i
% 255);
35 src_data
[i
* 4 + 1] = static_cast<unsigned char>(i
% 255);
36 src_data
[i
* 4 + 2] = static_cast<unsigned char>(i
% 255);
37 src_data
[i
* 4 + 3] = static_cast<unsigned char>(i
% 255);
41 // Fill the given data buffer with valid png data.
42 void FillBitmap(int w
, int h
, std::vector
<unsigned char>* output
) {
44 FillDataToBitmap(w
, h
, &bitmap
);
45 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap
, false, output
);
48 void SetFaviconRawBitmapResult(
50 favicon_base::IconType icon_type
,
52 std::vector
<favicon_base::FaviconRawBitmapResult
>* favicon_bitmap_results
) {
53 scoped_refptr
<base::RefCountedBytes
> data(new base::RefCountedBytes());
54 FillBitmap(gfx::kFaviconSize
, gfx::kFaviconSize
, &data
->data());
55 favicon_base::FaviconRawBitmapResult bitmap_result
;
56 bitmap_result
.expired
= expired
;
57 bitmap_result
.bitmap_data
= data
;
58 // Use a pixel size other than (0,0) as (0,0) has a special meaning.
59 bitmap_result
.pixel_size
= gfx::Size(gfx::kFaviconSize
, gfx::kFaviconSize
);
60 bitmap_result
.icon_type
= icon_type
;
61 bitmap_result
.icon_url
= icon_url
;
63 favicon_bitmap_results
->push_back(bitmap_result
);
66 void SetFaviconRawBitmapResult(
68 std::vector
<favicon_base::FaviconRawBitmapResult
>* favicon_bitmap_results
) {
69 SetFaviconRawBitmapResult(icon_url
,
70 favicon_base::FAVICON
,
72 favicon_bitmap_results
);
75 // This class is used to save the download request for verifying with test case.
76 // It also will be used to invoke the onDidDownload callback.
77 class DownloadHandler
{
79 explicit DownloadHandler(TestFaviconHandler
* favicon_helper
)
80 : favicon_helper_(favicon_helper
),
84 virtual ~DownloadHandler() {
88 download_
.reset(NULL
);
94 const GURL
& image_url
,
95 const std::vector
<int>& image_sizes
,
97 download_
.reset(new Download(
98 download_id
, image_url
, image_sizes
, max_image_size
, false));
101 void InvokeCallback();
103 void set_failed(bool failed
) { failed_
= failed
; }
105 bool HasDownload() const { return download_
.get() != NULL
; }
106 const GURL
& GetImageUrl() const { return download_
->image_url
; }
107 void SetImageSizes(const std::vector
<int>& sizes
) {
108 download_
->image_sizes
= sizes
; }
114 const std::vector
<int>& sizes
,
120 max_image_size(max_size
) {}
124 std::vector
<int> image_sizes
;
128 TestFaviconHandler
* favicon_helper_
;
129 scoped_ptr
<Download
> download_
;
132 DISALLOW_COPY_AND_ASSIGN(DownloadHandler
);
135 // This class is used to save the history request for verifying with test case.
136 // It also will be used to simulate the history response.
137 class HistoryRequestHandler
{
139 HistoryRequestHandler(const GURL
& page_url
,
140 const GURL
& icon_url
,
142 const favicon_base::FaviconResultsCallback
& callback
)
143 : page_url_(page_url
),
145 icon_type_(icon_type
),
146 callback_(callback
) {
149 HistoryRequestHandler(const GURL
& page_url
,
150 const GURL
& icon_url
,
152 const std::vector
<unsigned char>& bitmap_data
,
153 const gfx::Size
& size
)
154 : page_url_(page_url
),
156 icon_type_(icon_type
),
157 bitmap_data_(bitmap_data
),
161 virtual ~HistoryRequestHandler() {}
162 void InvokeCallback();
164 const GURL page_url_
;
165 const GURL icon_url_
;
166 const int icon_type_
;
167 const std::vector
<unsigned char> bitmap_data_
;
168 const gfx::Size size_
;
169 std::vector
<favicon_base::FaviconRawBitmapResult
> history_results_
;
170 favicon_base::FaviconResultsCallback callback_
;
173 DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler
);
178 class TestFaviconClient
: public FaviconClient
{
180 ~TestFaviconClient() override
{};
182 FaviconService
* GetFaviconService() override
{
183 // Just give none NULL value, so overridden methods can be hit.
184 return (FaviconService
*)(1);
187 bool IsBookmarked(const GURL
& url
) override
{ return false; }
190 class TestFaviconDriver
: public FaviconDriver
{
193 : favicon_validity_(false),
194 num_active_favicon_(0),
195 num_favicon_available_(0),
196 update_active_favicon_(false) {}
198 virtual ~TestFaviconDriver() {
201 bool IsOffTheRecord() override
{ return false; }
203 const gfx::Image
GetActiveFaviconImage() override
{ return image_
; }
205 const GURL
GetActiveFaviconURL() override
{ return favicon_url_
; }
207 bool GetActiveFaviconValidity() override
{ return favicon_validity_
; }
209 const GURL
GetActiveURL() override
{ return url_
; }
211 void SetActiveFaviconImage(gfx::Image image
) { image_
= image
; }
213 void SetActiveFaviconURL(GURL favicon_url
) { favicon_url_
= favicon_url
; }
215 void SetActiveFaviconValidity(bool favicon_validity
) {
216 favicon_validity_
= favicon_validity
;
219 int StartDownload(const GURL
& url
, int max_bitmap_size
) override
{
220 ADD_FAILURE() << "TestFaviconDriver::StartDownload() "
221 << "should never be called in tests.";
225 void OnFaviconAvailable(const gfx::Image
& image
,
226 const GURL
& icon_url
,
227 bool update_active_favicon
) override
{
228 ++num_favicon_available_
;
229 available_image_
= image
;
230 available_icon_url_
= icon_url
;
231 update_active_favicon_
= update_active_favicon
;
232 if (!update_active_favicon
)
235 ++num_active_favicon_
;
236 SetActiveFaviconURL(icon_url
);
237 SetActiveFaviconValidity(true);
238 SetActiveFaviconImage(image
);
241 size_t num_active_favicon() const { return num_active_favicon_
; }
242 size_t num_favicon_available() const { return num_favicon_available_
; }
243 void ResetNumActiveFavicon() { num_active_favicon_
= 0; }
244 void ResetNumFaviconAvailable() { num_favicon_available_
= 0; }
246 void SetActiveURL(GURL url
) { url_
= url
; }
248 const gfx::Image
available_favicon() { return available_image_
; }
250 const GURL
available_icon_url() { return available_icon_url_
; }
252 bool update_active_favicon() { return update_active_favicon_
; }
258 bool favicon_validity_
;
260 // The number of times that NotifyFaviconAvailable() has been called with
261 // |is_active_favicon| is true.
262 size_t num_active_favicon_
;
263 // The number of times that NotifyFaviconAvailable() has been called.
264 size_t num_favicon_available_
;
265 gfx::Image available_image_
;
266 GURL available_icon_url_
;
267 bool update_active_favicon_
;
269 DISALLOW_COPY_AND_ASSIGN(TestFaviconDriver
);
272 // This class is used to catch the FaviconHandler's download and history
273 // request, and also provide the methods to access the FaviconHandler
275 class TestFaviconHandler
: public FaviconHandler
{
277 static int GetMaximalIconSize(favicon_base::IconType icon_type
) {
278 return FaviconHandler::GetMaximalIconSize(icon_type
);
281 TestFaviconHandler(const GURL
& page_url
,
282 FaviconClient
* client
,
283 TestFaviconDriver
* driver
,
285 bool download_largest_icon
)
286 : FaviconHandler(client
, driver
, type
, download_largest_icon
),
288 driver
->SetActiveURL(page_url
);
289 download_handler_
.reset(new DownloadHandler(this));
292 ~TestFaviconHandler() override
{}
294 HistoryRequestHandler
* history_handler() {
295 return history_handler_
.get();
298 // This method will take the ownership of the given handler.
299 void set_history_handler(HistoryRequestHandler
* handler
) {
300 history_handler_
.reset(handler
);
303 DownloadHandler
* download_handler() {
304 return download_handler_
.get();
307 // Methods to access favicon internals.
308 const std::vector
<FaviconURL
>& urls() {
312 FaviconURL
* current_candidate() {
313 return FaviconHandler::current_candidate();
316 const FaviconCandidate
& best_favicon_candidate() {
317 return best_favicon_candidate_
;
321 void UpdateFaviconMappingAndFetch(
322 const GURL
& page_url
,
323 const GURL
& icon_url
,
324 favicon_base::IconType icon_type
,
325 const favicon_base::FaviconResultsCallback
& callback
,
326 base::CancelableTaskTracker
* tracker
) override
{
327 history_handler_
.reset(new HistoryRequestHandler(page_url
, icon_url
,
328 icon_type
, callback
));
331 void GetFaviconFromFaviconService(
332 const GURL
& icon_url
,
333 favicon_base::IconType icon_type
,
334 const favicon_base::FaviconResultsCallback
& callback
,
335 base::CancelableTaskTracker
* tracker
) override
{
336 history_handler_
.reset(new HistoryRequestHandler(GURL(), icon_url
,
337 icon_type
, callback
));
340 void GetFaviconForURLFromFaviconService(
341 const GURL
& page_url
,
343 const favicon_base::FaviconResultsCallback
& callback
,
344 base::CancelableTaskTracker
* tracker
) override
{
345 history_handler_
.reset(new HistoryRequestHandler(page_url
, GURL(),
346 icon_types
, callback
));
349 int DownloadFavicon(const GURL
& image_url
, int max_bitmap_size
) override
{
351 std::vector
<int> sizes
;
353 download_handler_
->AddDownload(
354 download_id_
, image_url
, sizes
, max_bitmap_size
);
358 void SetHistoryFavicons(const GURL
& page_url
,
359 const GURL
& icon_url
,
360 favicon_base::IconType icon_type
,
361 const gfx::Image
& image
) override
{
362 scoped_refptr
<base::RefCountedMemory
> bytes
= image
.As1xPNGBytes();
363 std::vector
<unsigned char> bitmap_data(bytes
->front(),
364 bytes
->front() + bytes
->size());
365 history_handler_
.reset(new HistoryRequestHandler(
366 page_url
, icon_url
, icon_type
, bitmap_data
, image
.Size()));
369 bool ShouldSaveFavicon(const GURL
& url
) override
{ return true; }
375 // The unique id of a download request. It will be returned to a
379 scoped_ptr
<DownloadHandler
> download_handler_
;
380 scoped_ptr
<HistoryRequestHandler
> history_handler_
;
382 DISALLOW_COPY_AND_ASSIGN(TestFaviconHandler
);
387 void HistoryRequestHandler::InvokeCallback() {
388 if (!callback_
.is_null()) {
389 callback_
.Run(history_results_
);
393 void DownloadHandler::InvokeCallback() {
394 std::vector
<gfx::Size
> original_bitmap_sizes
;
395 std::vector
<SkBitmap
> bitmaps
;
397 for (std::vector
<int>::const_iterator i
= download_
->image_sizes
.begin();
398 i
!= download_
->image_sizes
.end(); ++i
) {
399 int original_size
= (*i
> 0) ? *i
: gfx::kFaviconSize
;
400 int downloaded_size
= original_size
;
401 if (download_
->max_image_size
!= 0 &&
402 downloaded_size
> download_
->max_image_size
) {
403 downloaded_size
= download_
->max_image_size
;
406 FillDataToBitmap(downloaded_size
, downloaded_size
, &bitmap
);
407 bitmaps
.push_back(bitmap
);
408 original_bitmap_sizes
.push_back(gfx::Size(original_size
, original_size
));
411 favicon_helper_
->OnDidDownloadFavicon(download_
->download_id
,
412 download_
->image_url
,
414 original_bitmap_sizes
);
417 class FaviconHandlerTest
: public ChromeRenderViewHostTestHarness
{
419 FaviconHandlerTest() {
422 ~FaviconHandlerTest() override
{}
424 // Simulates requesting a favicon for |page_url| given:
425 // - We have not previously cached anything in history for |page_url| or for
426 // any of |candidates|.
427 // - The page provides favicons at |candidate_icons|.
428 // - The favicons at |candidate_icons| have edge pixel sizes of
429 // |candidate_icon_sizes|.
430 void DownloadTillDoneIgnoringHistory(
431 TestFaviconDriver
* favicon_driver
,
432 TestFaviconHandler
* favicon_handler
,
433 const GURL
& page_url
,
434 const std::vector
<FaviconURL
>& candidate_icons
,
435 const int* candidate_icon_sizes
) {
437 favicon_driver
, favicon_handler
, page_url
, candidate_icons
);
438 EXPECT_EQ(candidate_icons
.size(), favicon_handler
->image_urls().size());
440 DownloadHandler
* download_handler
= favicon_handler
->download_handler();
441 for (size_t i
= 0; i
< candidate_icons
.size(); ++i
) {
442 favicon_handler
->history_handler()->history_results_
.clear();
443 favicon_handler
->history_handler()->InvokeCallback();
444 ASSERT_TRUE(download_handler
->HasDownload());
445 EXPECT_EQ(download_handler
->GetImageUrl(),
446 candidate_icons
[i
].icon_url
);
447 std::vector
<int> sizes
;
448 sizes
.push_back(candidate_icon_sizes
[i
]);
449 download_handler
->SetImageSizes(sizes
);
450 download_handler
->InvokeCallback();
452 if (favicon_driver
->num_active_favicon())
457 void UpdateFaviconURL(TestFaviconDriver
* favicon_driver
,
458 TestFaviconHandler
* favicon_handler
,
459 const GURL
& page_url
,
460 const std::vector
<FaviconURL
>& candidate_icons
) {
461 favicon_driver
->ResetNumActiveFavicon();
463 favicon_handler
->FetchFavicon(page_url
);
464 favicon_handler
->history_handler()->InvokeCallback();
466 favicon_handler
->OnUpdateFaviconURL(candidate_icons
);
469 void SetUp() override
{
470 // The score computed by SelectFaviconFrames() is dependent on the supported
471 // scale factors of the platform. It is used for determining the goodness of
472 // a downloaded bitmap in FaviconHandler::OnDidDownloadFavicon().
473 // Force the values of the scale factors so that the tests produce the same
474 // results on all platforms.
475 std::vector
<ui::ScaleFactor
> scale_factors
;
476 scale_factors
.push_back(ui::SCALE_FACTOR_100P
);
477 scoped_set_supported_scale_factors_
.reset(
478 new ui::test::ScopedSetSupportedScaleFactors(scale_factors
));
480 ChromeRenderViewHostTestHarness::SetUp();
483 void TearDown() override
{
484 Profile
* profile
= Profile::FromBrowserContext(
485 web_contents()->GetBrowserContext());
486 FaviconServiceFactory::GetInstance()->SetTestingFactory(
488 ChromeRenderViewHostTestHarness::TearDown();
492 typedef scoped_ptr
<ui::test::ScopedSetSupportedScaleFactors
>
493 ScopedSetSupportedScaleFactors
;
494 ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_
;
495 DISALLOW_COPY_AND_ASSIGN(FaviconHandlerTest
);
498 TEST_F(FaviconHandlerTest
, GetFaviconFromHistory
) {
499 const GURL
page_url("http://www.google.com");
500 const GURL
icon_url("http://www.google.com/favicon");
502 TestFaviconDriver driver
;
503 TestFaviconClient client
;
504 TestFaviconHandler
helper(
505 page_url
, &client
, &driver
, FaviconHandler::FAVICON
, false);
507 helper
.FetchFavicon(page_url
);
508 HistoryRequestHandler
* history_handler
= helper
.history_handler();
509 // Ensure the data given to history is correct.
510 ASSERT_TRUE(history_handler
);
511 EXPECT_EQ(page_url
, history_handler
->page_url_
);
512 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
513 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
515 SetFaviconRawBitmapResult(icon_url
, &history_handler
->history_results_
);
517 // Send history response.
518 history_handler
->InvokeCallback();
519 // Verify FaviconHandler status
520 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
521 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
523 // Simulates update favicon url.
524 std::vector
<FaviconURL
> urls
;
526 FaviconURL(icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
527 helper
.OnUpdateFaviconURL(urls
);
529 // Verify FaviconHandler status
530 EXPECT_EQ(1U, helper
.urls().size());
531 ASSERT_TRUE(helper
.current_candidate());
532 ASSERT_EQ(icon_url
, helper
.current_candidate()->icon_url
);
533 ASSERT_EQ(favicon_base::FAVICON
, helper
.current_candidate()->icon_type
);
535 // Favicon shouldn't request to download icon.
536 EXPECT_FALSE(helper
.download_handler()->HasDownload());
539 TEST_F(FaviconHandlerTest
, DownloadFavicon
) {
540 const GURL
page_url("http://www.google.com");
541 const GURL
icon_url("http://www.google.com/favicon");
543 TestFaviconDriver driver
;
544 TestFaviconClient client
;
545 TestFaviconHandler
helper(
546 page_url
, &client
, &driver
, FaviconHandler::FAVICON
, false);
548 helper
.FetchFavicon(page_url
);
549 HistoryRequestHandler
* history_handler
= helper
.history_handler();
550 // Ensure the data given to history is correct.
551 ASSERT_TRUE(history_handler
);
552 EXPECT_EQ(page_url
, history_handler
->page_url_
);
553 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
554 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
556 // Set icon data expired
557 SetFaviconRawBitmapResult(icon_url
,
558 favicon_base::FAVICON
,
560 &history_handler
->history_results_
);
561 // Send history response.
562 history_handler
->InvokeCallback();
563 // Verify FaviconHandler status
564 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
565 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
567 // Simulates update favicon url.
568 std::vector
<FaviconURL
> urls
;
570 FaviconURL(icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
571 helper
.OnUpdateFaviconURL(urls
);
573 // Verify FaviconHandler status
574 EXPECT_EQ(1U, helper
.urls().size());
575 ASSERT_TRUE(helper
.current_candidate());
576 ASSERT_EQ(icon_url
, helper
.current_candidate()->icon_url
);
577 ASSERT_EQ(favicon_base::FAVICON
, helper
.current_candidate()->icon_type
);
579 // Favicon should request to download icon now.
580 DownloadHandler
* download_handler
= helper
.download_handler();
581 EXPECT_TRUE(helper
.download_handler()->HasDownload());
583 // Verify the download request.
584 EXPECT_EQ(icon_url
, download_handler
->GetImageUrl());
586 // Reset the history_handler to verify whether favicon is set.
587 helper
.set_history_handler(NULL
);
589 // Smulates download done.
590 download_handler
->InvokeCallback();
592 // New icon should be saved to history backend and navigation entry.
593 history_handler
= helper
.history_handler();
594 ASSERT_TRUE(history_handler
);
595 EXPECT_EQ(icon_url
, history_handler
->icon_url_
);
596 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
597 EXPECT_LT(0U, history_handler
->bitmap_data_
.size());
598 EXPECT_EQ(page_url
, history_handler
->page_url_
);
600 // Verify NavigationEntry.
601 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
602 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
603 EXPECT_FALSE(driver
.GetActiveFaviconImage().IsEmpty());
604 EXPECT_EQ(gfx::kFaviconSize
, driver
.GetActiveFaviconImage().Width());
607 TEST_F(FaviconHandlerTest
, UpdateAndDownloadFavicon
) {
608 const GURL
page_url("http://www.google.com");
609 const GURL
icon_url("http://www.google.com/favicon");
610 const GURL
new_icon_url("http://www.google.com/new_favicon");
612 TestFaviconDriver driver
;
613 TestFaviconClient client
;
614 TestFaviconHandler
helper(
615 page_url
, &client
, &driver
, FaviconHandler::FAVICON
, false);
617 helper
.FetchFavicon(page_url
);
618 HistoryRequestHandler
* history_handler
= helper
.history_handler();
619 // Ensure the data given to history is correct.
620 ASSERT_TRUE(history_handler
);
621 EXPECT_EQ(page_url
, history_handler
->page_url_
);
622 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
623 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
625 // Set valid icon data.
626 SetFaviconRawBitmapResult(icon_url
, &history_handler
->history_results_
);
628 // Send history response.
629 history_handler
->InvokeCallback();
630 // Verify FaviconHandler status.
631 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
632 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
634 // Reset the history_handler to verify whether new icon is requested from
636 helper
.set_history_handler(NULL
);
638 // Simulates update with the different favicon url.
639 std::vector
<FaviconURL
> urls
;
640 urls
.push_back(FaviconURL(
641 new_icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
642 helper
.OnUpdateFaviconURL(urls
);
644 // Verify FaviconHandler status.
645 EXPECT_EQ(1U, helper
.urls().size());
646 ASSERT_TRUE(helper
.current_candidate());
647 ASSERT_EQ(new_icon_url
, helper
.current_candidate()->icon_url
);
648 ASSERT_EQ(favicon_base::FAVICON
, helper
.current_candidate()->icon_type
);
650 // Favicon should be requested from history.
651 history_handler
= helper
.history_handler();
652 ASSERT_TRUE(history_handler
);
653 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
654 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
655 EXPECT_EQ(page_url
, history_handler
->page_url_
);
657 // Simulate not find icon.
658 history_handler
->history_results_
.clear();
659 history_handler
->InvokeCallback();
661 // Favicon should request to download icon now.
662 DownloadHandler
* download_handler
= helper
.download_handler();
663 EXPECT_TRUE(helper
.download_handler()->HasDownload());
665 // Verify the download request.
666 EXPECT_EQ(new_icon_url
, download_handler
->GetImageUrl());
668 // Reset the history_handler to verify whether favicon is set.
669 helper
.set_history_handler(NULL
);
671 // Smulates download done.
672 download_handler
->InvokeCallback();
674 // New icon should be saved to history backend and navigation entry.
675 history_handler
= helper
.history_handler();
676 ASSERT_TRUE(history_handler
);
677 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
678 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
679 EXPECT_LT(0U, history_handler
->bitmap_data_
.size());
680 EXPECT_EQ(page_url
, history_handler
->page_url_
);
682 // Verify NavigationEntry.
683 EXPECT_EQ(new_icon_url
, driver
.GetActiveFaviconURL());
684 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
685 EXPECT_FALSE(driver
.GetActiveFaviconImage().IsEmpty());
686 EXPECT_EQ(gfx::kFaviconSize
, driver
.GetActiveFaviconImage().Width());
689 TEST_F(FaviconHandlerTest
, FaviconInHistoryInvalid
) {
690 const GURL
page_url("http://www.google.com");
691 const GURL
icon_url("http://www.google.com/favicon");
693 TestFaviconDriver driver
;
694 TestFaviconClient client
;
695 TestFaviconHandler
helper(
696 page_url
, &client
, &driver
, FaviconHandler::FAVICON
, false);
698 helper
.FetchFavicon(page_url
);
699 HistoryRequestHandler
* history_handler
= helper
.history_handler();
700 // Ensure the data given to history is correct.
701 ASSERT_TRUE(history_handler
);
702 EXPECT_EQ(page_url
, history_handler
->page_url_
);
703 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
704 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
706 // Set non empty but invalid data.
707 favicon_base::FaviconRawBitmapResult bitmap_result
;
708 bitmap_result
.expired
= false;
709 // Empty bitmap data is invalid.
710 bitmap_result
.bitmap_data
= new base::RefCountedBytes();
711 bitmap_result
.pixel_size
= gfx::Size(gfx::kFaviconSize
, gfx::kFaviconSize
);
712 bitmap_result
.icon_type
= favicon_base::FAVICON
;
713 bitmap_result
.icon_url
= icon_url
;
714 history_handler
->history_results_
.clear();
715 history_handler
->history_results_
.push_back(bitmap_result
);
717 // Send history response.
718 history_handler
->InvokeCallback();
719 // The NavigationEntry should not be set yet as the history data is invalid.
720 EXPECT_FALSE(driver
.GetActiveFaviconValidity());
721 EXPECT_EQ(GURL(), driver
.GetActiveFaviconURL());
723 // Reset the history_handler to verify whether new icon is requested from
725 helper
.set_history_handler(NULL
);
727 // Simulates update with matching favicon URL.
728 std::vector
<FaviconURL
> urls
;
730 FaviconURL(icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
731 helper
.OnUpdateFaviconURL(urls
);
733 // A download for the favicon should be requested, and we should not do
734 // another history request.
735 DownloadHandler
* download_handler
= helper
.download_handler();
736 EXPECT_TRUE(helper
.download_handler()->HasDownload());
737 EXPECT_EQ(NULL
, helper
.history_handler());
739 // Verify the download request.
740 EXPECT_EQ(icon_url
, download_handler
->GetImageUrl());
742 // Simulates download done.
743 download_handler
->InvokeCallback();
745 // New icon should be saved to history backend and navigation entry.
746 history_handler
= helper
.history_handler();
747 ASSERT_TRUE(history_handler
);
748 EXPECT_EQ(icon_url
, history_handler
->icon_url_
);
749 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
750 EXPECT_LT(0U, history_handler
->bitmap_data_
.size());
751 EXPECT_EQ(page_url
, history_handler
->page_url_
);
753 // Verify NavigationEntry.
754 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
755 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
756 EXPECT_FALSE(driver
.GetActiveFaviconImage().IsEmpty());
757 EXPECT_EQ(gfx::kFaviconSize
, driver
.GetActiveFaviconImage().Width());
760 TEST_F(FaviconHandlerTest
, UpdateFavicon
) {
761 const GURL
page_url("http://www.google.com");
762 const GURL
icon_url("http://www.google.com/favicon");
763 const GURL
new_icon_url("http://www.google.com/new_favicon");
765 TestFaviconDriver driver
;
766 TestFaviconClient client
;
767 TestFaviconHandler
helper(
768 page_url
, &client
, &driver
, FaviconHandler::FAVICON
, false);
770 helper
.FetchFavicon(page_url
);
771 HistoryRequestHandler
* history_handler
= helper
.history_handler();
772 // Ensure the data given to history is correct.
773 ASSERT_TRUE(history_handler
);
774 EXPECT_EQ(page_url
, history_handler
->page_url_
);
775 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
776 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
778 SetFaviconRawBitmapResult(icon_url
, &history_handler
->history_results_
);
780 // Send history response.
781 history_handler
->InvokeCallback();
782 // Verify FaviconHandler status.
783 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
784 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
786 // Reset the history_handler to verify whether new icon is requested from
788 helper
.set_history_handler(NULL
);
790 // Simulates update with the different favicon url.
791 std::vector
<FaviconURL
> urls
;
792 urls
.push_back(FaviconURL(
793 new_icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
794 helper
.OnUpdateFaviconURL(urls
);
796 // Verify FaviconHandler status.
797 EXPECT_EQ(1U, helper
.urls().size());
798 ASSERT_TRUE(helper
.current_candidate());
799 ASSERT_EQ(new_icon_url
, helper
.current_candidate()->icon_url
);
800 ASSERT_EQ(favicon_base::FAVICON
, helper
.current_candidate()->icon_type
);
802 // Favicon should be requested from history.
803 history_handler
= helper
.history_handler();
804 ASSERT_TRUE(history_handler
);
805 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
806 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
807 EXPECT_EQ(page_url
, history_handler
->page_url_
);
809 // Simulate find icon.
810 SetFaviconRawBitmapResult(new_icon_url
, &history_handler
->history_results_
);
811 history_handler
->InvokeCallback();
813 // Shouldn't request download favicon
814 EXPECT_FALSE(helper
.download_handler()->HasDownload());
816 // Verify the favicon status.
817 EXPECT_EQ(new_icon_url
, driver
.GetActiveFaviconURL());
818 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
819 EXPECT_FALSE(driver
.GetActiveFaviconImage().IsEmpty());
822 TEST_F(FaviconHandlerTest
, Download2ndFaviconURLCandidate
) {
823 const GURL
page_url("http://www.google.com");
824 const GURL
icon_url("http://www.google.com/favicon");
825 const GURL
new_icon_url("http://www.google.com/new_favicon");
827 TestFaviconDriver driver
;
828 TestFaviconClient client
;
829 TestFaviconHandler
helper(
830 page_url
, &client
, &driver
, FaviconHandler::TOUCH
, false);
832 helper
.FetchFavicon(page_url
);
833 HistoryRequestHandler
* history_handler
= helper
.history_handler();
834 // Ensure the data given to history is correct.
835 ASSERT_TRUE(history_handler
);
836 EXPECT_EQ(page_url
, history_handler
->page_url_
);
837 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
838 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
| favicon_base::TOUCH_ICON
,
839 history_handler
->icon_type_
);
842 history_handler
->history_results_
.clear();
843 // Send history response.
844 history_handler
->InvokeCallback();
845 // Verify FaviconHandler status.
846 EXPECT_FALSE(driver
.GetActiveFaviconValidity());
847 EXPECT_EQ(GURL(), driver
.GetActiveFaviconURL());
849 // Reset the history_handler to verify whether new icon is requested from
851 helper
.set_history_handler(NULL
);
853 // Simulates update with the different favicon url.
854 std::vector
<FaviconURL
> urls
;
855 urls
.push_back(FaviconURL(icon_url
,
856 favicon_base::TOUCH_PRECOMPOSED_ICON
,
857 std::vector
<gfx::Size
>()));
858 urls
.push_back(FaviconURL(
859 new_icon_url
, favicon_base::TOUCH_ICON
, std::vector
<gfx::Size
>()));
860 urls
.push_back(FaviconURL(
861 new_icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
862 helper
.OnUpdateFaviconURL(urls
);
864 // Verify FaviconHandler status.
865 EXPECT_EQ(2U, helper
.urls().size());
866 ASSERT_TRUE(helper
.current_candidate());
867 ASSERT_EQ(icon_url
, helper
.current_candidate()->icon_url
);
868 ASSERT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
,
869 helper
.current_candidate()->icon_type
);
871 // Favicon should be requested from history.
872 history_handler
= helper
.history_handler();
873 ASSERT_TRUE(history_handler
);
874 EXPECT_EQ(icon_url
, history_handler
->icon_url_
);
875 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
, history_handler
->icon_type_
);
876 EXPECT_EQ(page_url
, history_handler
->page_url_
);
878 // Simulate not find icon.
879 history_handler
->history_results_
.clear();
880 history_handler
->InvokeCallback();
882 // Should request download favicon.
883 DownloadHandler
* download_handler
= helper
.download_handler();
884 EXPECT_TRUE(helper
.download_handler()->HasDownload());
886 // Verify the download request.
887 EXPECT_EQ(icon_url
, download_handler
->GetImageUrl());
889 // Reset the history_handler to verify whether favicon is request from
891 helper
.set_history_handler(NULL
);
892 // Smulates download failed.
893 download_handler
->set_failed(true);
894 download_handler
->InvokeCallback();
897 EXPECT_EQ(1U, helper
.urls().size());
898 ASSERT_TRUE(helper
.current_candidate());
899 EXPECT_EQ(new_icon_url
, helper
.current_candidate()->icon_url
);
900 EXPECT_EQ(favicon_base::TOUCH_ICON
, helper
.current_candidate()->icon_type
);
902 // Favicon should be requested from history.
903 history_handler
= helper
.history_handler();
904 ASSERT_TRUE(history_handler
);
905 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
906 EXPECT_EQ(favicon_base::TOUCH_ICON
, history_handler
->icon_type_
);
907 EXPECT_EQ(page_url
, history_handler
->page_url_
);
909 // Reset download handler
910 download_handler
->Reset();
912 // Simulates getting a expired icon from history.
913 SetFaviconRawBitmapResult(new_icon_url
,
914 favicon_base::TOUCH_ICON
,
916 &history_handler
->history_results_
);
917 history_handler
->InvokeCallback();
919 // Verify the download request.
920 EXPECT_TRUE(helper
.download_handler()->HasDownload());
921 EXPECT_EQ(new_icon_url
, download_handler
->GetImageUrl());
923 helper
.set_history_handler(NULL
);
925 // Simulates icon being downloaded.
926 download_handler
->InvokeCallback();
928 // New icon should be saved to history backend.
929 history_handler
= helper
.history_handler();
930 ASSERT_TRUE(history_handler
);
931 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
932 EXPECT_EQ(favicon_base::TOUCH_ICON
, history_handler
->icon_type_
);
933 EXPECT_LT(0U, history_handler
->bitmap_data_
.size());
934 EXPECT_EQ(page_url
, history_handler
->page_url_
);
937 TEST_F(FaviconHandlerTest
, UpdateDuringDownloading
) {
938 const GURL
page_url("http://www.google.com");
939 const GURL
icon_url("http://www.google.com/favicon");
940 const GURL
new_icon_url("http://www.google.com/new_favicon");
942 TestFaviconDriver driver
;
943 TestFaviconClient client
;
944 TestFaviconHandler
helper(
945 page_url
, &client
, &driver
, FaviconHandler::TOUCH
, false);
947 helper
.FetchFavicon(page_url
);
948 HistoryRequestHandler
* history_handler
= helper
.history_handler();
949 // Ensure the data given to history is correct.
950 ASSERT_TRUE(history_handler
);
951 EXPECT_EQ(page_url
, history_handler
->page_url_
);
952 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
953 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
| favicon_base::TOUCH_ICON
,
954 history_handler
->icon_type_
);
957 history_handler
->history_results_
.clear();
958 // Send history response.
959 history_handler
->InvokeCallback();
960 // Verify FaviconHandler status.
961 EXPECT_FALSE(driver
.GetActiveFaviconValidity());
962 EXPECT_EQ(GURL(), driver
.GetActiveFaviconURL());
964 // Reset the history_handler to verify whether new icon is requested from
966 helper
.set_history_handler(NULL
);
968 // Simulates update with the different favicon url.
969 std::vector
<FaviconURL
> urls
;
970 urls
.push_back(FaviconURL(icon_url
,
971 favicon_base::TOUCH_PRECOMPOSED_ICON
,
972 std::vector
<gfx::Size
>()));
973 urls
.push_back(FaviconURL(
974 new_icon_url
, favicon_base::TOUCH_ICON
, std::vector
<gfx::Size
>()));
975 urls
.push_back(FaviconURL(
976 new_icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
977 helper
.OnUpdateFaviconURL(urls
);
979 // Verify FaviconHandler status.
980 EXPECT_EQ(2U, helper
.urls().size());
981 ASSERT_TRUE(helper
.current_candidate());
982 ASSERT_EQ(icon_url
, helper
.current_candidate()->icon_url
);
983 ASSERT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
,
984 helper
.current_candidate()->icon_type
);
986 // Favicon should be requested from history.
987 history_handler
= helper
.history_handler();
988 ASSERT_TRUE(history_handler
);
989 EXPECT_EQ(icon_url
, history_handler
->icon_url_
);
990 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
, history_handler
->icon_type_
);
991 EXPECT_EQ(page_url
, history_handler
->page_url_
);
993 // Simulate not find icon.
994 history_handler
->history_results_
.clear();
995 history_handler
->InvokeCallback();
997 // Should request download favicon.
998 DownloadHandler
* download_handler
= helper
.download_handler();
999 EXPECT_TRUE(helper
.download_handler()->HasDownload());
1001 // Verify the download request.
1002 EXPECT_EQ(icon_url
, download_handler
->GetImageUrl());
1004 // Reset the history_handler to verify whether favicon is request from
1006 helper
.set_history_handler(NULL
);
1007 const GURL
latest_icon_url("http://www.google.com/latest_favicon");
1008 std::vector
<FaviconURL
> latest_urls
;
1009 latest_urls
.push_back(FaviconURL(
1010 latest_icon_url
, favicon_base::TOUCH_ICON
, std::vector
<gfx::Size
>()));
1011 helper
.OnUpdateFaviconURL(latest_urls
);
1013 EXPECT_EQ(1U, helper
.urls().size());
1014 EXPECT_EQ(latest_icon_url
, helper
.current_candidate()->icon_url
);
1015 EXPECT_EQ(favicon_base::TOUCH_ICON
, helper
.current_candidate()->icon_type
);
1017 // Whether new icon is requested from history
1018 history_handler
= helper
.history_handler();
1019 ASSERT_TRUE(history_handler
);
1020 EXPECT_EQ(latest_icon_url
, history_handler
->icon_url_
);
1021 EXPECT_EQ(favicon_base::TOUCH_ICON
, history_handler
->icon_type_
);
1022 EXPECT_EQ(page_url
, history_handler
->page_url_
);
1024 // Reset the history_handler to verify whether favicon is request from
1026 // Save the callback for late use.
1027 favicon_base::FaviconResultsCallback callback
= history_handler
->callback_
;
1028 helper
.set_history_handler(NULL
);
1030 // Simulates download succeed.
1031 download_handler
->InvokeCallback();
1032 // The downloaded icon should be thrown away as there is favicon update.
1033 EXPECT_FALSE(helper
.history_handler());
1035 download_handler
->Reset();
1037 // Simulates getting the icon from history.
1038 scoped_ptr
<HistoryRequestHandler
> handler
;
1039 handler
.reset(new HistoryRequestHandler(
1040 page_url
, latest_icon_url
, favicon_base::TOUCH_ICON
, callback
));
1041 SetFaviconRawBitmapResult(latest_icon_url
,
1042 favicon_base::TOUCH_ICON
,
1043 false /* expired */,
1044 &handler
->history_results_
);
1045 handler
->InvokeCallback();
1047 // No download request.
1048 EXPECT_FALSE(download_handler
->HasDownload());
1051 #if !defined(OS_ANDROID)
1053 // Test the favicon which is selected when the web page provides several
1054 // favicons and none of the favicons are cached in history.
1055 // The goal of this test is to be more of an integration test than
1056 // SelectFaviconFramesTest.*.
1057 TEST_F(FaviconHandlerTest
, MultipleFavicons
) {
1058 const GURL
kPageURL("http://www.google.com");
1059 const FaviconURL kSourceIconURLs
[] = {
1060 FaviconURL(GURL("http://www.google.com/a"),
1061 favicon_base::FAVICON
,
1062 std::vector
<gfx::Size
>()),
1063 FaviconURL(GURL("http://www.google.com/b"),
1064 favicon_base::FAVICON
,
1065 std::vector
<gfx::Size
>()),
1066 FaviconURL(GURL("http://www.google.com/c"),
1067 favicon_base::FAVICON
,
1068 std::vector
<gfx::Size
>()),
1069 FaviconURL(GURL("http://www.google.com/d"),
1070 favicon_base::FAVICON
,
1071 std::vector
<gfx::Size
>()),
1072 FaviconURL(GURL("http://www.google.com/e"),
1073 favicon_base::FAVICON
,
1074 std::vector
<gfx::Size
>())};
1076 // Set the supported scale factors to 1x and 2x. This affects the behavior of
1077 // SelectFaviconFrames().
1078 std::vector
<ui::ScaleFactor
> scale_factors
;
1079 scale_factors
.push_back(ui::SCALE_FACTOR_100P
);
1080 scale_factors
.push_back(ui::SCALE_FACTOR_200P
);
1081 ui::test::ScopedSetSupportedScaleFactors
scoped_supported(scale_factors
);
1083 // 1) Test that if there are several single resolution favicons to choose from
1084 // that the largest exact match is chosen.
1085 TestFaviconDriver driver1
;
1086 TestFaviconClient client
;
1087 TestFaviconHandler
handler1(
1088 kPageURL
, &client
, &driver1
, FaviconHandler::FAVICON
, false);
1090 const int kSizes1
[] = { 16, 24, 32, 48, 256 };
1091 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1092 kSourceIconURLs
+ arraysize(kSizes1
));
1093 DownloadTillDoneIgnoringHistory(
1094 &driver1
, &handler1
, kPageURL
, urls1
, kSizes1
);
1096 EXPECT_EQ(0u, handler1
.image_urls().size());
1097 EXPECT_TRUE(driver1
.GetActiveFaviconValidity());
1098 EXPECT_FALSE(driver1
.GetActiveFaviconImage().IsEmpty());
1099 EXPECT_EQ(gfx::kFaviconSize
, driver1
.GetActiveFaviconImage().Width());
1101 size_t expected_index
= 2u;
1102 EXPECT_EQ(32, kSizes1
[expected_index
]);
1103 EXPECT_EQ(kSourceIconURLs
[expected_index
].icon_url
,
1104 driver1
.GetActiveFaviconURL());
1106 // 2) Test that if there are several single resolution favicons to choose
1107 // from, the exact match is preferred even if it results in upsampling.
1108 TestFaviconDriver driver2
;
1109 TestFaviconHandler
handler2(
1110 kPageURL
, &client
, &driver2
, FaviconHandler::FAVICON
, false);
1112 const int kSizes2
[] = { 16, 24, 48, 256 };
1113 std::vector
<FaviconURL
> urls2(kSourceIconURLs
,
1114 kSourceIconURLs
+ arraysize(kSizes2
));
1115 DownloadTillDoneIgnoringHistory(
1116 &driver2
, &handler2
, kPageURL
, urls2
, kSizes2
);
1117 EXPECT_TRUE(driver2
.GetActiveFaviconValidity());
1118 expected_index
= 0u;
1119 EXPECT_EQ(16, kSizes2
[expected_index
]);
1120 EXPECT_EQ(kSourceIconURLs
[expected_index
].icon_url
,
1121 driver2
.GetActiveFaviconURL());
1123 // 3) Test that favicons which need to be upsampled a little or downsampled
1124 // a little are preferred over huge favicons.
1125 TestFaviconDriver driver3
;
1126 TestFaviconHandler
handler3(
1127 kPageURL
, &client
, &driver3
, FaviconHandler::FAVICON
, false);
1129 const int kSizes3
[] = { 256, 48 };
1130 std::vector
<FaviconURL
> urls3(kSourceIconURLs
,
1131 kSourceIconURLs
+ arraysize(kSizes3
));
1132 DownloadTillDoneIgnoringHistory(
1133 &driver3
, &handler3
, kPageURL
, urls3
, kSizes3
);
1134 EXPECT_TRUE(driver3
.GetActiveFaviconValidity());
1135 expected_index
= 1u;
1136 EXPECT_EQ(48, kSizes3
[expected_index
]);
1137 EXPECT_EQ(kSourceIconURLs
[expected_index
].icon_url
,
1138 driver3
.GetActiveFaviconURL());
1140 TestFaviconDriver driver4
;
1141 TestFaviconHandler
handler4(
1142 kPageURL
, &client
, &driver4
, FaviconHandler::FAVICON
, false);
1144 const int kSizes4
[] = { 17, 256 };
1145 std::vector
<FaviconURL
> urls4(kSourceIconURLs
,
1146 kSourceIconURLs
+ arraysize(kSizes4
));
1147 DownloadTillDoneIgnoringHistory(
1148 &driver4
, &handler4
, kPageURL
, urls4
, kSizes4
);
1149 EXPECT_TRUE(driver4
.GetActiveFaviconValidity());
1150 expected_index
= 0u;
1151 EXPECT_EQ(17, kSizes4
[expected_index
]);
1152 EXPECT_EQ(kSourceIconURLs
[expected_index
].icon_url
,
1153 driver4
.GetActiveFaviconURL());
1158 TEST_F(FaviconHandlerTest
, TestSortFavicon
) {
1159 const GURL
kPageURL("http://www.google.com");
1160 std::vector
<gfx::Size
> icon1
;
1161 icon1
.push_back(gfx::Size(1024, 1024));
1162 icon1
.push_back(gfx::Size(512, 512));
1164 std::vector
<gfx::Size
> icon2
;
1165 icon2
.push_back(gfx::Size(15, 15));
1166 icon2
.push_back(gfx::Size(16, 16));
1168 std::vector
<gfx::Size
> icon3
;
1169 icon3
.push_back(gfx::Size(16, 16));
1170 icon3
.push_back(gfx::Size(14, 14));
1172 const FaviconURL kSourceIconURLs
[] = {
1173 FaviconURL(GURL("http://www.google.com/a"), favicon_base::FAVICON
, icon1
),
1174 FaviconURL(GURL("http://www.google.com/b"), favicon_base::FAVICON
, icon2
),
1175 FaviconURL(GURL("http://www.google.com/c"), favicon_base::FAVICON
, icon3
),
1176 FaviconURL(GURL("http://www.google.com/d"),
1177 favicon_base::FAVICON
,
1178 std::vector
<gfx::Size
>()),
1179 FaviconURL(GURL("http://www.google.com/e"),
1180 favicon_base::FAVICON
,
1181 std::vector
<gfx::Size
>())};
1183 TestFaviconClient client
;
1184 TestFaviconDriver driver1
;
1185 TestFaviconHandler
handler1(
1186 kPageURL
, &client
, &driver1
, FaviconHandler::FAVICON
, true);
1187 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1188 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1189 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1191 struct ExpectedResult
{
1192 // The favicon's index in kSourceIconURLs.
1193 size_t favicon_index
;
1194 // Width of largest bitmap.
1197 // First is icon1, though its size larger than maximal.
1200 // The 16x16 is largest.
1202 // Third is icon3 though it has same size as icon2.
1203 // The 16x16 is largest.
1205 // The rest of bitmaps come in order, there is no sizes attribute.
1209 const std::vector
<FaviconURL
>& icons
= handler1
.image_urls();
1210 ASSERT_EQ(5u, icons
.size());
1211 for (size_t i
= 0; i
< icons
.size(); ++i
) {
1212 EXPECT_EQ(kSourceIconURLs
[results
[i
].favicon_index
].icon_url
,
1214 if (results
[i
].width
!= -1)
1215 EXPECT_EQ(results
[i
].width
, icons
[i
].icon_sizes
[0].width());
1219 TEST_F(FaviconHandlerTest
, TestDownloadLargestFavicon
) {
1220 const GURL
kPageURL("http://www.google.com");
1221 std::vector
<gfx::Size
> icon1
;
1222 icon1
.push_back(gfx::Size(1024, 1024));
1223 icon1
.push_back(gfx::Size(512, 512));
1225 std::vector
<gfx::Size
> icon2
;
1226 icon2
.push_back(gfx::Size(15, 15));
1227 icon2
.push_back(gfx::Size(14, 14));
1229 std::vector
<gfx::Size
> icon3
;
1230 icon3
.push_back(gfx::Size(16, 16));
1231 icon3
.push_back(gfx::Size(512, 512));
1233 const FaviconURL kSourceIconURLs
[] = {
1235 GURL("http://www.google.com/a"), favicon_base::FAVICON
, icon1
),
1237 GURL("http://www.google.com/b"), favicon_base::FAVICON
, icon2
),
1239 GURL("http://www.google.com/c"), favicon_base::FAVICON
, icon3
),
1240 FaviconURL(GURL("http://www.google.com/d"),
1241 favicon_base::FAVICON
,
1242 std::vector
<gfx::Size
>()),
1243 FaviconURL(GURL("http://www.google.com/e"),
1244 favicon_base::FAVICON
,
1245 std::vector
<gfx::Size
>())};
1247 TestFaviconClient client
;
1248 TestFaviconDriver driver1
;
1249 TestFaviconHandler
handler1(
1250 kPageURL
, &client
, &driver1
, FaviconHandler::FAVICON
, true);
1251 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1252 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1253 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1255 // Simulate the download failed, to check whether the icons were requested
1256 // to download according their size.
1257 struct ExpectedResult
{
1258 // The size of image_urls_.
1259 size_t image_urls_size
;
1260 // The favicon's index in kSourceIconURLs.
1261 size_t favicon_index
;
1262 // Width of largest bitmap.
1268 // The rest of bitmaps come in order.
1273 for (int i
= 0; i
< 5; ++i
) {
1274 ASSERT_EQ(results
[i
].image_urls_size
, handler1
.image_urls().size());
1275 EXPECT_EQ(kSourceIconURLs
[results
[i
].favicon_index
].icon_url
,
1276 handler1
.current_candidate()->icon_url
);
1277 if (results
[i
].width
!= -1) {
1278 EXPECT_EQ(results
[i
].width
, handler1
.current_candidate()->
1279 icon_sizes
[0].width());
1282 // Simulate no favicon from history.
1283 handler1
.history_handler()->history_results_
.clear();
1284 handler1
.history_handler()->InvokeCallback();
1286 // Verify download request
1287 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1288 EXPECT_EQ(kSourceIconURLs
[results
[i
].favicon_index
].icon_url
,
1289 handler1
.download_handler()->GetImageUrl());
1291 // Simulate the download failed.
1292 handler1
.download_handler()->set_failed(true);
1293 handler1
.download_handler()->InvokeCallback();
1297 TEST_F(FaviconHandlerTest
, TestSelectLargestFavicon
) {
1298 const GURL
kPageURL("http://www.google.com");
1300 std::vector
<gfx::Size
> one_icon
;
1301 one_icon
.push_back(gfx::Size(15, 15));
1303 std::vector
<gfx::Size
> two_icons
;
1304 two_icons
.push_back(gfx::Size(14, 14));
1305 two_icons
.push_back(gfx::Size(16, 16));
1307 const FaviconURL kSourceIconURLs
[] = {
1309 GURL("http://www.google.com/b"), favicon_base::FAVICON
, one_icon
),
1311 GURL("http://www.google.com/c"), favicon_base::FAVICON
, two_icons
)};
1313 TestFaviconClient client
;
1314 TestFaviconDriver driver1
;
1315 TestFaviconHandler
handler1(
1316 kPageURL
, &client
, &driver1
, FaviconHandler::FAVICON
, true);
1317 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1318 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1319 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1321 ASSERT_EQ(2u, handler1
.urls().size());
1323 // Index of largest favicon in kSourceIconURLs.
1325 // The largest bitmap's index in Favicon .
1328 // Verify the icon_bitmaps_ was initialized correctly.
1329 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
,
1330 handler1
.current_candidate()->icon_url
);
1331 EXPECT_EQ(kSourceIconURLs
[i
].icon_sizes
[b
],
1332 handler1
.current_candidate()->icon_sizes
[0]);
1334 // Simulate no favicon from history.
1335 handler1
.history_handler()->history_results_
.clear();
1336 handler1
.history_handler()->InvokeCallback();
1338 // Verify download request
1339 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1340 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
,
1341 handler1
.download_handler()->GetImageUrl());
1343 // Give the correct download result.
1344 std::vector
<int> sizes
;
1345 for (std::vector
<gfx::Size
>::const_iterator j
=
1346 kSourceIconURLs
[i
].icon_sizes
.begin();
1347 j
!= kSourceIconURLs
[i
].icon_sizes
.end(); ++j
)
1348 sizes
.push_back(j
->width());
1350 handler1
.download_handler()->SetImageSizes(sizes
);
1351 handler1
.download_handler()->InvokeCallback();
1353 // Verify the largest bitmap has been saved into history.
1354 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
, handler1
.history_handler()->icon_url_
);
1355 EXPECT_EQ(kSourceIconURLs
[i
].icon_sizes
[b
],
1356 handler1
.history_handler()->size_
);
1357 // Verify NotifyFaviconAvailable().
1358 EXPECT_FALSE(driver1
.update_active_favicon());
1359 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
, driver1
.available_icon_url());
1360 EXPECT_EQ(kSourceIconURLs
[i
].icon_sizes
[b
],
1361 driver1
.available_favicon().Size());
1364 TEST_F(FaviconHandlerTest
, TestFaviconWasScaledAfterDownload
) {
1365 const GURL
kPageURL("http://www.google.com");
1366 const int kMaximalSize
=
1367 TestFaviconHandler::GetMaximalIconSize(favicon_base::FAVICON
);
1369 std::vector
<gfx::Size
> icon1
;
1370 icon1
.push_back(gfx::Size(kMaximalSize
+ 1, kMaximalSize
+ 1));
1372 std::vector
<gfx::Size
> icon2
;
1373 icon2
.push_back(gfx::Size(kMaximalSize
+ 2, kMaximalSize
+ 2));
1375 const FaviconURL kSourceIconURLs
[] = {
1377 GURL("http://www.google.com/b"), favicon_base::FAVICON
, icon1
),
1379 GURL("http://www.google.com/c"), favicon_base::FAVICON
, icon2
)};
1381 TestFaviconClient client
;
1382 TestFaviconDriver driver1
;
1383 TestFaviconHandler
handler1(
1384 kPageURL
, &client
, &driver1
, FaviconHandler::FAVICON
, true);
1385 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1386 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1387 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1389 ASSERT_EQ(2u, handler1
.urls().size());
1391 // Index of largest favicon in kSourceIconURLs.
1393 // The largest bitmap's index in Favicon .
1396 // Verify the icon_bitmaps_ was initialized correctly.
1397 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
,
1398 handler1
.current_candidate()->icon_url
);
1399 EXPECT_EQ(kSourceIconURLs
[i
].icon_sizes
[b
],
1400 handler1
.current_candidate()->icon_sizes
[0]);
1402 // Simulate no favicon from history.
1403 handler1
.history_handler()->history_results_
.clear();
1404 handler1
.history_handler()->InvokeCallback();
1406 // Verify download request
1407 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1408 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
,
1409 handler1
.download_handler()->GetImageUrl());
1411 // Give the scaled download bitmap.
1412 std::vector
<int> sizes
;
1413 sizes
.push_back(kMaximalSize
);
1415 handler1
.download_handler()->SetImageSizes(sizes
);
1416 handler1
.download_handler()->InvokeCallback();
1418 // Verify the largest bitmap has been saved into history though it was
1419 // scaled down to maximal size and smaller than icon1 now.
1420 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
, handler1
.history_handler()->icon_url_
);
1421 EXPECT_EQ(gfx::Size(kMaximalSize
, kMaximalSize
),
1422 handler1
.history_handler()->size_
);
1425 TEST_F(FaviconHandlerTest
, TestKeepDownloadedLargestFavicon
) {
1426 const GURL
kPageURL("http://www.google.com");
1428 std::vector
<gfx::Size
> icon1
;
1429 icon1
.push_back(gfx::Size(16, 16));
1430 const int actual_size1
= 10;
1432 std::vector
<gfx::Size
> icon2
;
1433 icon2
.push_back(gfx::Size(15, 15));
1434 const int actual_size2
= 12;
1436 const FaviconURL kSourceIconURLs
[] = {
1437 FaviconURL(GURL("http://www.google.com/b"), favicon_base::FAVICON
, icon1
),
1438 FaviconURL(GURL("http://www.google.com/c"), favicon_base::FAVICON
, icon2
),
1439 FaviconURL(GURL("http://www.google.com/d"),
1440 favicon_base::FAVICON
,
1441 std::vector
<gfx::Size
>())};
1443 TestFaviconClient client
;
1444 TestFaviconDriver driver1
;
1445 TestFaviconHandler
handler1(
1446 kPageURL
, &client
, &driver1
, FaviconHandler::FAVICON
, true);
1447 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1448 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1449 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1450 ASSERT_EQ(3u, handler1
.urls().size());
1452 // Simulate no favicon from history.
1453 handler1
.history_handler()->history_results_
.clear();
1454 handler1
.history_handler()->InvokeCallback();
1456 // Verify the first icon was request to download
1457 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1458 EXPECT_EQ(kSourceIconURLs
[0].icon_url
,
1459 handler1
.download_handler()->GetImageUrl());
1461 // Give the incorrect size.
1462 std::vector
<int> sizes
;
1463 sizes
.push_back(actual_size1
);
1464 handler1
.download_handler()->SetImageSizes(sizes
);
1465 handler1
.download_handler()->InvokeCallback();
1467 // Simulate no favicon from history.
1468 handler1
.history_handler()->history_results_
.clear();
1469 handler1
.history_handler()->InvokeCallback();
1471 // Verify the 2nd icon was request to download
1472 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1473 EXPECT_EQ(kSourceIconURLs
[1].icon_url
,
1474 handler1
.download_handler()->GetImageUrl());
1476 // Very the best candidate is icon1
1477 EXPECT_EQ(kSourceIconURLs
[0].icon_url
,
1478 handler1
.best_favicon_candidate().image_url
);
1479 EXPECT_EQ(gfx::Size(actual_size1
, actual_size1
),
1480 handler1
.best_favicon_candidate().image
.Size());
1482 // Give the incorrect size.
1484 sizes
.push_back(actual_size2
);
1485 handler1
.download_handler()->SetImageSizes(sizes
);
1486 handler1
.download_handler()->InvokeCallback();
1488 // Verify icon2 has been saved into history.
1489 EXPECT_EQ(kSourceIconURLs
[1].icon_url
, handler1
.history_handler()->icon_url_
);
1490 EXPECT_EQ(gfx::Size(actual_size2
, actual_size2
),
1491 handler1
.history_handler()->size_
);
1494 static KeyedService
* BuildFaviconService(content::BrowserContext
* profile
) {
1495 FaviconClient
* favicon_client
=
1496 ChromeFaviconClientFactory::GetForProfile(static_cast<Profile
*>(profile
));
1497 return new FaviconService(static_cast<Profile
*>(profile
), favicon_client
);
1500 static KeyedService
* BuildHistoryService(content::BrowserContext
* profile
) {
1504 // Test that Favicon is not requested repeatedly during the same session if
1505 // server returns HTTP 404 status.
1506 TEST_F(FaviconHandlerTest
, UnableToDownloadFavicon
) {
1507 const GURL
missing_icon_url("http://www.google.com/favicon.ico");
1508 const GURL
another_icon_url("http://www.youtube.com/favicon.ico");
1510 Profile
* profile
= Profile::FromBrowserContext(
1511 web_contents()->GetBrowserContext());
1513 FaviconServiceFactory::GetInstance()->SetTestingFactory(
1514 profile
, BuildFaviconService
);
1516 HistoryServiceFactory::GetInstance()->SetTestingFactory(
1517 profile
, BuildHistoryService
);
1519 FaviconService
* favicon_service
= FaviconServiceFactory::GetForProfile(
1520 profile
, ServiceAccessType::IMPLICIT_ACCESS
);
1522 FaviconTabHelper::CreateForWebContents(web_contents());
1523 FaviconTabHelper
* favicon_tab_helper
=
1524 FaviconTabHelper::FromWebContents(web_contents());
1526 std::vector
<SkBitmap
> empty_icons
;
1527 std::vector
<gfx::Size
> empty_icon_sizes
;
1528 int download_id
= 0;
1530 // Try to download missing icon.
1531 download_id
= favicon_tab_helper
->StartDownload(missing_icon_url
, 0);
1532 EXPECT_NE(0, download_id
);
1533 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1535 // Report download failure with HTTP 503 status.
1536 favicon_tab_helper
->DidDownloadFavicon(download_id
, 503, missing_icon_url
,
1537 empty_icons
, empty_icon_sizes
);
1538 // Icon is not marked as UnableToDownload as HTTP status is not 404.
1539 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1541 // Try to download again.
1542 download_id
= favicon_tab_helper
->StartDownload(missing_icon_url
, 0);
1543 EXPECT_NE(0, download_id
);
1544 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1546 // Report download failure with HTTP 404 status.
1547 favicon_tab_helper
->DidDownloadFavicon(download_id
, 404, missing_icon_url
,
1548 empty_icons
, empty_icon_sizes
);
1549 // Icon is marked as UnableToDownload.
1550 EXPECT_TRUE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1552 // Try to download again.
1553 download_id
= favicon_tab_helper
->StartDownload(missing_icon_url
, 0);
1554 // Download is not started and Icon is still marked as UnableToDownload.
1555 EXPECT_EQ(0, download_id
);
1556 EXPECT_TRUE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1558 // Try to download another icon.
1559 download_id
= favicon_tab_helper
->StartDownload(another_icon_url
, 0);
1560 // Download is started as another icon URL is not same as missing_icon_url.
1561 EXPECT_NE(0, download_id
);
1562 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(another_icon_url
));
1564 // Clear the list of missing icons.
1565 favicon_service
->ClearUnableToDownloadFavicons();
1566 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1567 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(another_icon_url
));
1569 // Try to download again.
1570 download_id
= favicon_tab_helper
->StartDownload(missing_icon_url
, 0);
1571 EXPECT_NE(0, download_id
);
1572 // Report download success with HTTP 200 status.
1573 favicon_tab_helper
->DidDownloadFavicon(download_id
, 200, missing_icon_url
,
1574 empty_icons
, empty_icon_sizes
);
1575 // Icon is not marked as UnableToDownload as HTTP status is not 404.
1576 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1579 class FaviconHandlerActiveFaviconValidityParamTest
:
1580 public FaviconHandlerTest
,
1581 public ::testing::WithParamInterface
<bool> {
1583 FaviconHandlerActiveFaviconValidityParamTest() {}
1585 ~FaviconHandlerActiveFaviconValidityParamTest() override
{}
1587 bool GetActiveFaviconValiditySetting() {
1592 DISALLOW_COPY_AND_ASSIGN(FaviconHandlerActiveFaviconValidityParamTest
);
1595 TEST_P(FaviconHandlerActiveFaviconValidityParamTest
,
1596 TestDownloadLargestIconDoesNotImpactActiveFaviconValidity
) {
1597 const GURL
page_url("http://www.google.com");
1599 std::vector
<gfx::Size
> one_icon
;
1600 one_icon
.push_back(gfx::Size(15, 15));
1602 const GURL
old_favicon_url("http://www.google.com/old");
1603 const GURL
new_favicon_url("http://www.google.com/b");
1604 const FaviconURL source_icon_urls
[] = {
1605 FaviconURL(new_favicon_url
, favicon_base::FAVICON
, one_icon
)};
1606 TestFaviconClient client
;
1607 TestFaviconDriver driver1
;
1608 TestFaviconHandler
handler1(
1609 page_url
, &client
, &driver1
, FaviconHandler::FAVICON
, true);
1610 std::vector
<FaviconURL
> urls1(source_icon_urls
,
1611 source_icon_urls
+ arraysize(source_icon_urls
));
1612 UpdateFaviconURL(&driver1
, &handler1
, page_url
, urls1
);
1614 HistoryRequestHandler
* history_handler
= handler1
.history_handler();
1616 // Simulate the active favicon is updated, this shouldn't happen in real
1617 // use case, but we want to verify the behavior below is not impacted by
1619 driver1
.SetActiveFaviconValidity(GetActiveFaviconValiditySetting());
1620 // Simulate the get favicon from history, but favicon URL didn't match.
1621 SetFaviconRawBitmapResult(old_favicon_url
,
1622 &history_handler
->history_results_
);
1623 history_handler
->InvokeCallback();
1624 // Since we downloaded largest icon, and don't want to set active favicon
1625 // NotifyFaviconAvaliable() should be called with is_active_favicon as false.
1626 EXPECT_EQ(old_favicon_url
, driver1
.available_icon_url());
1627 EXPECT_FALSE(driver1
.update_active_favicon());
1628 EXPECT_EQ(1u, driver1
.num_favicon_available());
1630 // We are trying to get favicon from history again.
1631 history_handler
= handler1
.history_handler();
1632 EXPECT_EQ(new_favicon_url
, history_handler
->icon_url_
);
1633 // Simulate the get expired favicon from history.
1634 history_handler
->history_results_
.clear();
1635 SetFaviconRawBitmapResult(new_favicon_url
, favicon_base::FAVICON
, true,
1636 &history_handler
->history_results_
);
1637 history_handler
->InvokeCallback();
1638 // Since we downloaded largest icon, and don't want to set active favicon
1639 // NotifyFaviconAvaliable() should be called with is_active_favicon as false.
1640 EXPECT_EQ(new_favicon_url
, driver1
.available_icon_url());
1641 EXPECT_FALSE(driver1
.update_active_favicon());
1642 EXPECT_EQ(2u, driver1
.num_favicon_available());
1644 // We are trying to download favicon.
1645 DownloadHandler
* download_handler
= handler1
.download_handler();
1646 EXPECT_TRUE(download_handler
->HasDownload());
1647 EXPECT_EQ(new_favicon_url
, download_handler
->GetImageUrl());
1648 // Simulate the download succeed.
1649 download_handler
->InvokeCallback();
1650 // Since we downloaded largest icon, and don't want to set active favicon
1651 // NotifyFaviconAvaliable() should be called with is_active_favicon as false.
1652 EXPECT_EQ(new_favicon_url
, driver1
.available_icon_url());
1653 EXPECT_FALSE(driver1
.update_active_favicon());
1654 EXPECT_EQ(3u, driver1
.num_favicon_available());
1657 INSTANTIATE_TEST_CASE_P(FaviconHandlerTestActiveFaviconValidityTrueOrFalse
,
1658 FaviconHandlerActiveFaviconValidityParamTest
,