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 "components/favicon/core/favicon_handler.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "chrome/browser/favicon/chrome_favicon_client_factory.h"
9 #include "chrome/browser/favicon/favicon_service_factory.h"
10 #include "chrome/browser/favicon/favicon_tab_helper.h"
11 #include "chrome/browser/history/history_service_factory.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
14 #include "components/favicon/core/favicon_service.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 favicon::FaviconURL
;
26 // Fill the given bmp with valid png data.
27 void FillDataToBitmap(int w
, int h
, SkBitmap
* bmp
) {
28 bmp
->allocN32Pixels(w
, h
);
30 unsigned char* src_data
=
31 reinterpret_cast<unsigned char*>(bmp
->getAddr32(0, 0));
32 for (int i
= 0; i
< w
* h
; i
++) {
33 src_data
[i
* 4 + 0] = static_cast<unsigned char>(i
% 255);
34 src_data
[i
* 4 + 1] = static_cast<unsigned char>(i
% 255);
35 src_data
[i
* 4 + 2] = static_cast<unsigned char>(i
% 255);
36 src_data
[i
* 4 + 3] = static_cast<unsigned char>(i
% 255);
40 // Fill the given data buffer with valid png data.
41 void FillBitmap(int w
, int h
, std::vector
<unsigned char>* output
) {
43 FillDataToBitmap(w
, h
, &bitmap
);
44 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap
, false, output
);
47 void SetFaviconRawBitmapResult(
49 favicon_base::IconType icon_type
,
51 std::vector
<favicon_base::FaviconRawBitmapResult
>* favicon_bitmap_results
) {
52 scoped_refptr
<base::RefCountedBytes
> data(new base::RefCountedBytes());
53 FillBitmap(gfx::kFaviconSize
, gfx::kFaviconSize
, &data
->data());
54 favicon_base::FaviconRawBitmapResult bitmap_result
;
55 bitmap_result
.expired
= expired
;
56 bitmap_result
.bitmap_data
= data
;
57 // Use a pixel size other than (0,0) as (0,0) has a special meaning.
58 bitmap_result
.pixel_size
= gfx::Size(gfx::kFaviconSize
, gfx::kFaviconSize
);
59 bitmap_result
.icon_type
= icon_type
;
60 bitmap_result
.icon_url
= icon_url
;
62 favicon_bitmap_results
->push_back(bitmap_result
);
65 void SetFaviconRawBitmapResult(
67 std::vector
<favicon_base::FaviconRawBitmapResult
>* favicon_bitmap_results
) {
68 SetFaviconRawBitmapResult(icon_url
,
69 favicon_base::FAVICON
,
71 favicon_bitmap_results
);
74 // This class is used to save the download request for verifying with test case.
75 // It also will be used to invoke the onDidDownload callback.
76 class DownloadHandler
{
78 explicit DownloadHandler(TestFaviconHandler
* favicon_helper
)
79 : favicon_helper_(favicon_helper
),
92 const GURL
& image_url
,
93 const std::vector
<int>& image_sizes
,
95 download_
.reset(new Download(
96 download_id
, image_url
, image_sizes
, max_image_size
, false));
99 void InvokeCallback();
101 void set_failed(bool failed
) { failed_
= failed
; }
103 bool HasDownload() const { return download_
.get(); }
104 const GURL
& GetImageUrl() const { return download_
->image_url
; }
105 void SetImageSizes(const std::vector
<int>& sizes
) {
106 download_
->image_sizes
= sizes
; }
112 const std::vector
<int>& sizes
,
118 max_image_size(max_size
) {}
122 std::vector
<int> image_sizes
;
126 TestFaviconHandler
* favicon_helper_
;
127 scoped_ptr
<Download
> download_
;
130 DISALLOW_COPY_AND_ASSIGN(DownloadHandler
);
133 // This class is used to save the history request for verifying with test case.
134 // It also will be used to simulate the history response.
135 class HistoryRequestHandler
{
137 HistoryRequestHandler(const GURL
& page_url
,
138 const GURL
& icon_url
,
140 const favicon_base::FaviconResultsCallback
& callback
)
141 : page_url_(page_url
),
143 icon_type_(icon_type
),
144 callback_(callback
) {
147 HistoryRequestHandler(const GURL
& page_url
,
148 const GURL
& icon_url
,
150 const std::vector
<unsigned char>& bitmap_data
,
151 const gfx::Size
& size
)
152 : page_url_(page_url
),
154 icon_type_(icon_type
),
155 bitmap_data_(bitmap_data
),
159 ~HistoryRequestHandler() {}
160 void InvokeCallback();
162 const GURL page_url_
;
163 const GURL icon_url_
;
164 const int icon_type_
;
165 const std::vector
<unsigned char> bitmap_data_
;
166 const gfx::Size size_
;
167 std::vector
<favicon_base::FaviconRawBitmapResult
> history_results_
;
168 favicon_base::FaviconResultsCallback callback_
;
171 DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler
);
176 class TestFaviconDriver
: public favicon::FaviconDriver
{
179 : favicon_validity_(false),
180 num_active_favicon_(0),
181 num_favicon_available_(0),
182 update_active_favicon_(false) {}
184 ~TestFaviconDriver() override
{}
186 int StartDownload(const GURL
& url
, int max_bitmap_size
) override
{
187 ADD_FAILURE() << "TestFaviconDriver::StartDownload() "
188 << "should never be called in tests.";
192 bool IsOffTheRecord() override
{ return false; }
194 bool IsBookmarked(const GURL
& url
) override
{ return false; }
196 GURL
GetActiveURL() override
{ return url_
; }
198 base::string16
GetActiveTitle() override
{ return base::string16(); }
200 bool GetActiveFaviconValidity() override
{ return favicon_validity_
; }
202 void SetActiveFaviconValidity(bool favicon_validity
) override
{
203 favicon_validity_
= favicon_validity
;
206 GURL
GetActiveFaviconURL() override
{ return favicon_url_
; }
208 void SetActiveFaviconURL(const GURL
& favicon_url
) override
{
209 favicon_url_
= favicon_url
;
212 gfx::Image
GetActiveFaviconImage() override
{ return image_
; }
214 void SetActiveFaviconImage(const gfx::Image
& image
) override
{
218 void OnFaviconAvailable(const gfx::Image
& image
,
219 const GURL
& icon_url
,
220 bool update_active_favicon
) override
{
221 ++num_favicon_available_
;
222 available_image_
= image
;
223 available_icon_url_
= icon_url
;
224 update_active_favicon_
= update_active_favicon
;
225 if (!update_active_favicon
)
228 ++num_active_favicon_
;
229 SetActiveFaviconURL(icon_url
);
230 SetActiveFaviconValidity(true);
231 SetActiveFaviconImage(image
);
234 size_t num_active_favicon() const { return num_active_favicon_
; }
235 size_t num_favicon_available() const { return num_favicon_available_
; }
236 void ResetNumActiveFavicon() { num_active_favicon_
= 0; }
237 void ResetNumFaviconAvailable() { num_favicon_available_
= 0; }
239 void SetActiveURL(GURL url
) { url_
= url
; }
241 const gfx::Image
available_favicon() { return available_image_
; }
243 const GURL
available_icon_url() { return available_icon_url_
; }
245 bool update_active_favicon() { return update_active_favicon_
; }
251 bool favicon_validity_
;
253 // The number of times that NotifyFaviconAvailable() has been called with
254 // |is_active_favicon| is true.
255 size_t num_active_favicon_
;
256 // The number of times that NotifyFaviconAvailable() has been called.
257 size_t num_favicon_available_
;
258 gfx::Image available_image_
;
259 GURL available_icon_url_
;
260 bool update_active_favicon_
;
262 DISALLOW_COPY_AND_ASSIGN(TestFaviconDriver
);
265 // This class is used to catch the FaviconHandler's download and history
266 // request, and also provide the methods to access the FaviconHandler
268 class TestFaviconHandler
: public favicon::FaviconHandler
{
270 static int GetMaximalIconSize(favicon_base::IconType icon_type
) {
271 return FaviconHandler::GetMaximalIconSize(icon_type
);
274 TestFaviconHandler(const GURL
& page_url
,
275 TestFaviconDriver
* driver
,
277 bool download_largest_icon
)
278 : favicon::FaviconHandler(nullptr,
281 download_largest_icon
),
283 driver
->SetActiveURL(page_url
);
284 download_handler_
.reset(new DownloadHandler(this));
287 ~TestFaviconHandler() override
{}
289 HistoryRequestHandler
* history_handler() {
290 return history_handler_
.get();
293 // This method will take the ownership of the given handler.
294 void set_history_handler(HistoryRequestHandler
* handler
) {
295 history_handler_
.reset(handler
);
298 DownloadHandler
* download_handler() {
299 return download_handler_
.get();
302 // Methods to access favicon internals.
303 const std::vector
<FaviconURL
>& urls() {
307 FaviconURL
* current_candidate() {
308 return favicon::FaviconHandler::current_candidate();
311 const FaviconCandidate
& best_favicon_candidate() {
312 return best_favicon_candidate_
;
316 void UpdateFaviconMappingAndFetch(
317 const GURL
& page_url
,
318 const GURL
& icon_url
,
319 favicon_base::IconType icon_type
,
320 const favicon_base::FaviconResultsCallback
& callback
,
321 base::CancelableTaskTracker
* tracker
) override
{
322 history_handler_
.reset(new HistoryRequestHandler(page_url
, icon_url
,
323 icon_type
, callback
));
326 void GetFaviconFromFaviconService(
327 const GURL
& icon_url
,
328 favicon_base::IconType icon_type
,
329 const favicon_base::FaviconResultsCallback
& callback
,
330 base::CancelableTaskTracker
* tracker
) override
{
331 history_handler_
.reset(new HistoryRequestHandler(GURL(), icon_url
,
332 icon_type
, callback
));
335 void GetFaviconForURLFromFaviconService(
336 const GURL
& page_url
,
338 const favicon_base::FaviconResultsCallback
& callback
,
339 base::CancelableTaskTracker
* tracker
) override
{
340 history_handler_
.reset(new HistoryRequestHandler(page_url
, GURL(),
341 icon_types
, callback
));
344 int DownloadFavicon(const GURL
& image_url
, int max_bitmap_size
) override
{
346 std::vector
<int> sizes
;
348 download_handler_
->AddDownload(
349 download_id_
, image_url
, sizes
, max_bitmap_size
);
353 void SetHistoryFavicons(const GURL
& page_url
,
354 const GURL
& icon_url
,
355 favicon_base::IconType icon_type
,
356 const gfx::Image
& image
) override
{
357 scoped_refptr
<base::RefCountedMemory
> bytes
= image
.As1xPNGBytes();
358 std::vector
<unsigned char> bitmap_data(bytes
->front(),
359 bytes
->front() + bytes
->size());
360 history_handler_
.reset(new HistoryRequestHandler(
361 page_url
, icon_url
, icon_type
, bitmap_data
, image
.Size()));
364 bool ShouldSaveFavicon(const GURL
& url
) override
{ return true; }
370 // The unique id of a download request. It will be returned to a
374 scoped_ptr
<DownloadHandler
> download_handler_
;
375 scoped_ptr
<HistoryRequestHandler
> history_handler_
;
377 DISALLOW_COPY_AND_ASSIGN(TestFaviconHandler
);
382 void HistoryRequestHandler::InvokeCallback() {
383 if (!callback_
.is_null()) {
384 callback_
.Run(history_results_
);
388 void DownloadHandler::InvokeCallback() {
389 std::vector
<gfx::Size
> original_bitmap_sizes
;
390 std::vector
<SkBitmap
> bitmaps
;
392 for (std::vector
<int>::const_iterator i
= download_
->image_sizes
.begin();
393 i
!= download_
->image_sizes
.end(); ++i
) {
394 int original_size
= (*i
> 0) ? *i
: gfx::kFaviconSize
;
395 int downloaded_size
= original_size
;
396 if (download_
->max_image_size
!= 0 &&
397 downloaded_size
> download_
->max_image_size
) {
398 downloaded_size
= download_
->max_image_size
;
401 FillDataToBitmap(downloaded_size
, downloaded_size
, &bitmap
);
402 bitmaps
.push_back(bitmap
);
403 original_bitmap_sizes
.push_back(gfx::Size(original_size
, original_size
));
406 favicon_helper_
->OnDidDownloadFavicon(download_
->download_id
,
407 download_
->image_url
,
409 original_bitmap_sizes
);
412 class FaviconHandlerTest
: public ChromeRenderViewHostTestHarness
{
414 FaviconHandlerTest() {
417 ~FaviconHandlerTest() override
{}
419 // Simulates requesting a favicon for |page_url| given:
420 // - We have not previously cached anything in history for |page_url| or for
421 // any of |candidates|.
422 // - The page provides favicons at |candidate_icons|.
423 // - The favicons at |candidate_icons| have edge pixel sizes of
424 // |candidate_icon_sizes|.
425 void DownloadTillDoneIgnoringHistory(
426 TestFaviconDriver
* favicon_driver
,
427 TestFaviconHandler
* favicon_handler
,
428 const GURL
& page_url
,
429 const std::vector
<FaviconURL
>& candidate_icons
,
430 const int* candidate_icon_sizes
) {
432 favicon_driver
, favicon_handler
, page_url
, candidate_icons
);
433 EXPECT_EQ(candidate_icons
.size(), favicon_handler
->image_urls().size());
435 DownloadHandler
* download_handler
= favicon_handler
->download_handler();
436 for (size_t i
= 0; i
< candidate_icons
.size(); ++i
) {
437 favicon_handler
->history_handler()->history_results_
.clear();
438 favicon_handler
->history_handler()->InvokeCallback();
439 ASSERT_TRUE(download_handler
->HasDownload());
440 EXPECT_EQ(download_handler
->GetImageUrl(),
441 candidate_icons
[i
].icon_url
);
442 std::vector
<int> sizes
;
443 sizes
.push_back(candidate_icon_sizes
[i
]);
444 download_handler
->SetImageSizes(sizes
);
445 download_handler
->InvokeCallback();
447 if (favicon_driver
->num_active_favicon())
452 void UpdateFaviconURL(TestFaviconDriver
* favicon_driver
,
453 TestFaviconHandler
* favicon_handler
,
454 const GURL
& page_url
,
455 const std::vector
<FaviconURL
>& candidate_icons
) {
456 favicon_driver
->ResetNumActiveFavicon();
458 favicon_handler
->FetchFavicon(page_url
);
459 favicon_handler
->history_handler()->InvokeCallback();
461 favicon_handler
->OnUpdateFaviconURL(candidate_icons
);
464 void SetUp() override
{
465 // The score computed by SelectFaviconFrames() is dependent on the supported
466 // scale factors of the platform. It is used for determining the goodness of
467 // a downloaded bitmap in favicon::FaviconHandler::OnDidDownloadFavicon().
468 // Force the values of the scale factors so that the tests produce the same
469 // results on all platforms.
470 std::vector
<ui::ScaleFactor
> scale_factors
;
471 scale_factors
.push_back(ui::SCALE_FACTOR_100P
);
472 scoped_set_supported_scale_factors_
.reset(
473 new ui::test::ScopedSetSupportedScaleFactors(scale_factors
));
475 ChromeRenderViewHostTestHarness::SetUp();
478 void TearDown() override
{
479 Profile
* profile
= Profile::FromBrowserContext(
480 web_contents()->GetBrowserContext());
481 FaviconServiceFactory::GetInstance()->SetTestingFactory(profile
, nullptr);
482 ChromeRenderViewHostTestHarness::TearDown();
486 typedef scoped_ptr
<ui::test::ScopedSetSupportedScaleFactors
>
487 ScopedSetSupportedScaleFactors
;
488 ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_
;
489 DISALLOW_COPY_AND_ASSIGN(FaviconHandlerTest
);
492 TEST_F(FaviconHandlerTest
, GetFaviconFromHistory
) {
493 const GURL
page_url("http://www.google.com");
494 const GURL
icon_url("http://www.google.com/favicon");
496 TestFaviconDriver driver
;
497 TestFaviconHandler
helper(page_url
, &driver
, favicon::FaviconHandler::FAVICON
,
500 helper
.FetchFavicon(page_url
);
501 HistoryRequestHandler
* history_handler
= helper
.history_handler();
502 // Ensure the data given to history is correct.
503 ASSERT_TRUE(history_handler
);
504 EXPECT_EQ(page_url
, history_handler
->page_url_
);
505 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
506 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
508 SetFaviconRawBitmapResult(icon_url
, &history_handler
->history_results_
);
510 // Send history response.
511 history_handler
->InvokeCallback();
512 // Verify FaviconHandler status
513 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
514 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
516 // Simulates update favicon url.
517 std::vector
<FaviconURL
> urls
;
519 FaviconURL(icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
520 helper
.OnUpdateFaviconURL(urls
);
522 // Verify FaviconHandler status
523 EXPECT_EQ(1U, helper
.urls().size());
524 ASSERT_TRUE(helper
.current_candidate());
525 ASSERT_EQ(icon_url
, helper
.current_candidate()->icon_url
);
526 ASSERT_EQ(favicon_base::FAVICON
, helper
.current_candidate()->icon_type
);
528 // Favicon shouldn't request to download icon.
529 EXPECT_FALSE(helper
.download_handler()->HasDownload());
532 TEST_F(FaviconHandlerTest
, DownloadFavicon
) {
533 const GURL
page_url("http://www.google.com");
534 const GURL
icon_url("http://www.google.com/favicon");
536 TestFaviconDriver driver
;
537 TestFaviconHandler
helper(page_url
, &driver
, favicon::FaviconHandler::FAVICON
,
540 helper
.FetchFavicon(page_url
);
541 HistoryRequestHandler
* history_handler
= helper
.history_handler();
542 // Ensure the data given to history is correct.
543 ASSERT_TRUE(history_handler
);
544 EXPECT_EQ(page_url
, history_handler
->page_url_
);
545 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
546 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
548 // Set icon data expired
549 SetFaviconRawBitmapResult(icon_url
,
550 favicon_base::FAVICON
,
552 &history_handler
->history_results_
);
553 // Send history response.
554 history_handler
->InvokeCallback();
555 // Verify FaviconHandler status
556 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
557 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
559 // Simulates update favicon url.
560 std::vector
<FaviconURL
> urls
;
562 FaviconURL(icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
563 helper
.OnUpdateFaviconURL(urls
);
565 // Verify FaviconHandler status
566 EXPECT_EQ(1U, helper
.urls().size());
567 ASSERT_TRUE(helper
.current_candidate());
568 ASSERT_EQ(icon_url
, helper
.current_candidate()->icon_url
);
569 ASSERT_EQ(favicon_base::FAVICON
, helper
.current_candidate()->icon_type
);
571 // Favicon should request to download icon now.
572 DownloadHandler
* download_handler
= helper
.download_handler();
573 EXPECT_TRUE(helper
.download_handler()->HasDownload());
575 // Verify the download request.
576 EXPECT_EQ(icon_url
, download_handler
->GetImageUrl());
578 // Reset the history_handler to verify whether favicon is set.
579 helper
.set_history_handler(nullptr);
581 // Smulates download done.
582 download_handler
->InvokeCallback();
584 // New icon should be saved to history backend and navigation entry.
585 history_handler
= helper
.history_handler();
586 ASSERT_TRUE(history_handler
);
587 EXPECT_EQ(icon_url
, history_handler
->icon_url_
);
588 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
589 EXPECT_LT(0U, history_handler
->bitmap_data_
.size());
590 EXPECT_EQ(page_url
, history_handler
->page_url_
);
592 // Verify NavigationEntry.
593 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
594 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
595 EXPECT_FALSE(driver
.GetActiveFaviconImage().IsEmpty());
596 EXPECT_EQ(gfx::kFaviconSize
, driver
.GetActiveFaviconImage().Width());
599 TEST_F(FaviconHandlerTest
, UpdateAndDownloadFavicon
) {
600 const GURL
page_url("http://www.google.com");
601 const GURL
icon_url("http://www.google.com/favicon");
602 const GURL
new_icon_url("http://www.google.com/new_favicon");
604 TestFaviconDriver driver
;
605 TestFaviconHandler
helper(page_url
, &driver
, favicon::FaviconHandler::FAVICON
,
608 helper
.FetchFavicon(page_url
);
609 HistoryRequestHandler
* history_handler
= helper
.history_handler();
610 // Ensure the data given to history is correct.
611 ASSERT_TRUE(history_handler
);
612 EXPECT_EQ(page_url
, history_handler
->page_url_
);
613 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
614 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
616 // Set valid icon data.
617 SetFaviconRawBitmapResult(icon_url
, &history_handler
->history_results_
);
619 // Send history response.
620 history_handler
->InvokeCallback();
621 // Verify FaviconHandler status.
622 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
623 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
625 // Reset the history_handler to verify whether new icon is requested from
627 helper
.set_history_handler(nullptr);
629 // Simulates update with the different favicon url.
630 std::vector
<FaviconURL
> urls
;
631 urls
.push_back(FaviconURL(
632 new_icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
633 helper
.OnUpdateFaviconURL(urls
);
635 // Verify FaviconHandler status.
636 EXPECT_EQ(1U, helper
.urls().size());
637 ASSERT_TRUE(helper
.current_candidate());
638 ASSERT_EQ(new_icon_url
, helper
.current_candidate()->icon_url
);
639 ASSERT_EQ(favicon_base::FAVICON
, helper
.current_candidate()->icon_type
);
641 // Favicon should be requested from history.
642 history_handler
= helper
.history_handler();
643 ASSERT_TRUE(history_handler
);
644 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
645 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
646 EXPECT_EQ(page_url
, history_handler
->page_url_
);
648 // Simulate not find icon.
649 history_handler
->history_results_
.clear();
650 history_handler
->InvokeCallback();
652 // Favicon should request to download icon now.
653 DownloadHandler
* download_handler
= helper
.download_handler();
654 EXPECT_TRUE(helper
.download_handler()->HasDownload());
656 // Verify the download request.
657 EXPECT_EQ(new_icon_url
, download_handler
->GetImageUrl());
659 // Reset the history_handler to verify whether favicon is set.
660 helper
.set_history_handler(nullptr);
662 // Smulates download done.
663 download_handler
->InvokeCallback();
665 // New icon should be saved to history backend and navigation entry.
666 history_handler
= helper
.history_handler();
667 ASSERT_TRUE(history_handler
);
668 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
669 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
670 EXPECT_LT(0U, history_handler
->bitmap_data_
.size());
671 EXPECT_EQ(page_url
, history_handler
->page_url_
);
673 // Verify NavigationEntry.
674 EXPECT_EQ(new_icon_url
, driver
.GetActiveFaviconURL());
675 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
676 EXPECT_FALSE(driver
.GetActiveFaviconImage().IsEmpty());
677 EXPECT_EQ(gfx::kFaviconSize
, driver
.GetActiveFaviconImage().Width());
680 TEST_F(FaviconHandlerTest
, FaviconInHistoryInvalid
) {
681 const GURL
page_url("http://www.google.com");
682 const GURL
icon_url("http://www.google.com/favicon");
684 TestFaviconDriver driver
;
685 TestFaviconHandler
helper(page_url
, &driver
, favicon::FaviconHandler::FAVICON
,
688 helper
.FetchFavicon(page_url
);
689 HistoryRequestHandler
* history_handler
= helper
.history_handler();
690 // Ensure the data given to history is correct.
691 ASSERT_TRUE(history_handler
);
692 EXPECT_EQ(page_url
, history_handler
->page_url_
);
693 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
694 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
696 // Set non empty but invalid data.
697 favicon_base::FaviconRawBitmapResult bitmap_result
;
698 bitmap_result
.expired
= false;
699 // Empty bitmap data is invalid.
700 bitmap_result
.bitmap_data
= new base::RefCountedBytes();
701 bitmap_result
.pixel_size
= gfx::Size(gfx::kFaviconSize
, gfx::kFaviconSize
);
702 bitmap_result
.icon_type
= favicon_base::FAVICON
;
703 bitmap_result
.icon_url
= icon_url
;
704 history_handler
->history_results_
.clear();
705 history_handler
->history_results_
.push_back(bitmap_result
);
707 // Send history response.
708 history_handler
->InvokeCallback();
709 // The NavigationEntry should not be set yet as the history data is invalid.
710 EXPECT_FALSE(driver
.GetActiveFaviconValidity());
711 EXPECT_EQ(GURL(), driver
.GetActiveFaviconURL());
713 // Reset the history_handler to verify whether new icon is requested from
715 helper
.set_history_handler(nullptr);
717 // Simulates update with matching favicon URL.
718 std::vector
<FaviconURL
> urls
;
720 FaviconURL(icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
721 helper
.OnUpdateFaviconURL(urls
);
723 // A download for the favicon should be requested, and we should not do
724 // another history request.
725 DownloadHandler
* download_handler
= helper
.download_handler();
726 EXPECT_TRUE(helper
.download_handler()->HasDownload());
727 EXPECT_EQ(nullptr, helper
.history_handler());
729 // Verify the download request.
730 EXPECT_EQ(icon_url
, download_handler
->GetImageUrl());
732 // Simulates download done.
733 download_handler
->InvokeCallback();
735 // New icon should be saved to history backend and navigation entry.
736 history_handler
= helper
.history_handler();
737 ASSERT_TRUE(history_handler
);
738 EXPECT_EQ(icon_url
, history_handler
->icon_url_
);
739 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
740 EXPECT_LT(0U, history_handler
->bitmap_data_
.size());
741 EXPECT_EQ(page_url
, history_handler
->page_url_
);
743 // Verify NavigationEntry.
744 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
745 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
746 EXPECT_FALSE(driver
.GetActiveFaviconImage().IsEmpty());
747 EXPECT_EQ(gfx::kFaviconSize
, driver
.GetActiveFaviconImage().Width());
750 TEST_F(FaviconHandlerTest
, UpdateFavicon
) {
751 const GURL
page_url("http://www.google.com");
752 const GURL
icon_url("http://www.google.com/favicon");
753 const GURL
new_icon_url("http://www.google.com/new_favicon");
755 TestFaviconDriver driver
;
756 TestFaviconHandler
helper(page_url
, &driver
, favicon::FaviconHandler::FAVICON
,
759 helper
.FetchFavicon(page_url
);
760 HistoryRequestHandler
* history_handler
= helper
.history_handler();
761 // Ensure the data given to history is correct.
762 ASSERT_TRUE(history_handler
);
763 EXPECT_EQ(page_url
, history_handler
->page_url_
);
764 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
765 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
767 SetFaviconRawBitmapResult(icon_url
, &history_handler
->history_results_
);
769 // Send history response.
770 history_handler
->InvokeCallback();
771 // Verify FaviconHandler status.
772 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
773 EXPECT_EQ(icon_url
, driver
.GetActiveFaviconURL());
775 // Reset the history_handler to verify whether new icon is requested from
777 helper
.set_history_handler(nullptr);
779 // Simulates update with the different favicon url.
780 std::vector
<FaviconURL
> urls
;
781 urls
.push_back(FaviconURL(
782 new_icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
783 helper
.OnUpdateFaviconURL(urls
);
785 // Verify FaviconHandler status.
786 EXPECT_EQ(1U, helper
.urls().size());
787 ASSERT_TRUE(helper
.current_candidate());
788 ASSERT_EQ(new_icon_url
, helper
.current_candidate()->icon_url
);
789 ASSERT_EQ(favicon_base::FAVICON
, helper
.current_candidate()->icon_type
);
791 // Favicon should be requested from history.
792 history_handler
= helper
.history_handler();
793 ASSERT_TRUE(history_handler
);
794 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
795 EXPECT_EQ(favicon_base::FAVICON
, history_handler
->icon_type_
);
796 EXPECT_EQ(page_url
, history_handler
->page_url_
);
798 // Simulate find icon.
799 SetFaviconRawBitmapResult(new_icon_url
, &history_handler
->history_results_
);
800 history_handler
->InvokeCallback();
802 // Shouldn't request download favicon
803 EXPECT_FALSE(helper
.download_handler()->HasDownload());
805 // Verify the favicon status.
806 EXPECT_EQ(new_icon_url
, driver
.GetActiveFaviconURL());
807 EXPECT_TRUE(driver
.GetActiveFaviconValidity());
808 EXPECT_FALSE(driver
.GetActiveFaviconImage().IsEmpty());
811 TEST_F(FaviconHandlerTest
, Download2ndFaviconURLCandidate
) {
812 const GURL
page_url("http://www.google.com");
813 const GURL
icon_url("http://www.google.com/favicon");
814 const GURL
new_icon_url("http://www.google.com/new_favicon");
816 TestFaviconDriver driver
;
817 TestFaviconHandler
helper(page_url
, &driver
, favicon::FaviconHandler::TOUCH
,
820 helper
.FetchFavicon(page_url
);
821 HistoryRequestHandler
* history_handler
= helper
.history_handler();
822 // Ensure the data given to history is correct.
823 ASSERT_TRUE(history_handler
);
824 EXPECT_EQ(page_url
, history_handler
->page_url_
);
825 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
826 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
| favicon_base::TOUCH_ICON
,
827 history_handler
->icon_type_
);
830 history_handler
->history_results_
.clear();
831 // Send history response.
832 history_handler
->InvokeCallback();
833 // Verify FaviconHandler status.
834 EXPECT_FALSE(driver
.GetActiveFaviconValidity());
835 EXPECT_EQ(GURL(), driver
.GetActiveFaviconURL());
837 // Reset the history_handler to verify whether new icon is requested from
839 helper
.set_history_handler(nullptr);
841 // Simulates update with the different favicon url.
842 std::vector
<FaviconURL
> urls
;
843 urls
.push_back(FaviconURL(icon_url
,
844 favicon_base::TOUCH_PRECOMPOSED_ICON
,
845 std::vector
<gfx::Size
>()));
846 urls
.push_back(FaviconURL(
847 new_icon_url
, favicon_base::TOUCH_ICON
, std::vector
<gfx::Size
>()));
848 urls
.push_back(FaviconURL(
849 new_icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
850 helper
.OnUpdateFaviconURL(urls
);
852 // Verify FaviconHandler status.
853 EXPECT_EQ(2U, helper
.urls().size());
854 ASSERT_TRUE(helper
.current_candidate());
855 ASSERT_EQ(icon_url
, helper
.current_candidate()->icon_url
);
856 ASSERT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
,
857 helper
.current_candidate()->icon_type
);
859 // Favicon should be requested from history.
860 history_handler
= helper
.history_handler();
861 ASSERT_TRUE(history_handler
);
862 EXPECT_EQ(icon_url
, history_handler
->icon_url_
);
863 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
, history_handler
->icon_type_
);
864 EXPECT_EQ(page_url
, history_handler
->page_url_
);
866 // Simulate not find icon.
867 history_handler
->history_results_
.clear();
868 history_handler
->InvokeCallback();
870 // Should request download favicon.
871 DownloadHandler
* download_handler
= helper
.download_handler();
872 EXPECT_TRUE(helper
.download_handler()->HasDownload());
874 // Verify the download request.
875 EXPECT_EQ(icon_url
, download_handler
->GetImageUrl());
877 // Reset the history_handler to verify whether favicon is request from
879 helper
.set_history_handler(nullptr);
880 // Smulates download failed.
881 download_handler
->set_failed(true);
882 download_handler
->InvokeCallback();
885 EXPECT_EQ(1U, helper
.urls().size());
886 ASSERT_TRUE(helper
.current_candidate());
887 EXPECT_EQ(new_icon_url
, helper
.current_candidate()->icon_url
);
888 EXPECT_EQ(favicon_base::TOUCH_ICON
, helper
.current_candidate()->icon_type
);
890 // Favicon should be requested from history.
891 history_handler
= helper
.history_handler();
892 ASSERT_TRUE(history_handler
);
893 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
894 EXPECT_EQ(favicon_base::TOUCH_ICON
, history_handler
->icon_type_
);
895 EXPECT_EQ(page_url
, history_handler
->page_url_
);
897 // Reset download handler
898 download_handler
->Reset();
900 // Simulates getting a expired icon from history.
901 SetFaviconRawBitmapResult(new_icon_url
,
902 favicon_base::TOUCH_ICON
,
904 &history_handler
->history_results_
);
905 history_handler
->InvokeCallback();
907 // Verify the download request.
908 EXPECT_TRUE(helper
.download_handler()->HasDownload());
909 EXPECT_EQ(new_icon_url
, download_handler
->GetImageUrl());
911 helper
.set_history_handler(nullptr);
913 // Simulates icon being downloaded.
914 download_handler
->InvokeCallback();
916 // New icon should be saved to history backend.
917 history_handler
= helper
.history_handler();
918 ASSERT_TRUE(history_handler
);
919 EXPECT_EQ(new_icon_url
, history_handler
->icon_url_
);
920 EXPECT_EQ(favicon_base::TOUCH_ICON
, history_handler
->icon_type_
);
921 EXPECT_LT(0U, history_handler
->bitmap_data_
.size());
922 EXPECT_EQ(page_url
, history_handler
->page_url_
);
925 TEST_F(FaviconHandlerTest
, UpdateDuringDownloading
) {
926 const GURL
page_url("http://www.google.com");
927 const GURL
icon_url("http://www.google.com/favicon");
928 const GURL
new_icon_url("http://www.google.com/new_favicon");
930 TestFaviconDriver driver
;
931 TestFaviconHandler
helper(page_url
, &driver
, favicon::FaviconHandler::TOUCH
,
934 helper
.FetchFavicon(page_url
);
935 HistoryRequestHandler
* history_handler
= helper
.history_handler();
936 // Ensure the data given to history is correct.
937 ASSERT_TRUE(history_handler
);
938 EXPECT_EQ(page_url
, history_handler
->page_url_
);
939 EXPECT_EQ(GURL(), history_handler
->icon_url_
);
940 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
| favicon_base::TOUCH_ICON
,
941 history_handler
->icon_type_
);
944 history_handler
->history_results_
.clear();
945 // Send history response.
946 history_handler
->InvokeCallback();
947 // Verify FaviconHandler status.
948 EXPECT_FALSE(driver
.GetActiveFaviconValidity());
949 EXPECT_EQ(GURL(), driver
.GetActiveFaviconURL());
951 // Reset the history_handler to verify whether new icon is requested from
953 helper
.set_history_handler(nullptr);
955 // Simulates update with the different favicon url.
956 std::vector
<FaviconURL
> urls
;
957 urls
.push_back(FaviconURL(icon_url
,
958 favicon_base::TOUCH_PRECOMPOSED_ICON
,
959 std::vector
<gfx::Size
>()));
960 urls
.push_back(FaviconURL(
961 new_icon_url
, favicon_base::TOUCH_ICON
, std::vector
<gfx::Size
>()));
962 urls
.push_back(FaviconURL(
963 new_icon_url
, favicon_base::FAVICON
, std::vector
<gfx::Size
>()));
964 helper
.OnUpdateFaviconURL(urls
);
966 // Verify FaviconHandler status.
967 EXPECT_EQ(2U, helper
.urls().size());
968 ASSERT_TRUE(helper
.current_candidate());
969 ASSERT_EQ(icon_url
, helper
.current_candidate()->icon_url
);
970 ASSERT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
,
971 helper
.current_candidate()->icon_type
);
973 // Favicon should be requested from history.
974 history_handler
= helper
.history_handler();
975 ASSERT_TRUE(history_handler
);
976 EXPECT_EQ(icon_url
, history_handler
->icon_url_
);
977 EXPECT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON
, history_handler
->icon_type_
);
978 EXPECT_EQ(page_url
, history_handler
->page_url_
);
980 // Simulate not find icon.
981 history_handler
->history_results_
.clear();
982 history_handler
->InvokeCallback();
984 // Should request download favicon.
985 DownloadHandler
* download_handler
= helper
.download_handler();
986 EXPECT_TRUE(helper
.download_handler()->HasDownload());
988 // Verify the download request.
989 EXPECT_EQ(icon_url
, download_handler
->GetImageUrl());
991 // Reset the history_handler to verify whether favicon is request from
993 helper
.set_history_handler(nullptr);
994 const GURL
latest_icon_url("http://www.google.com/latest_favicon");
995 std::vector
<FaviconURL
> latest_urls
;
996 latest_urls
.push_back(FaviconURL(
997 latest_icon_url
, favicon_base::TOUCH_ICON
, std::vector
<gfx::Size
>()));
998 helper
.OnUpdateFaviconURL(latest_urls
);
1000 EXPECT_EQ(1U, helper
.urls().size());
1001 EXPECT_EQ(latest_icon_url
, helper
.current_candidate()->icon_url
);
1002 EXPECT_EQ(favicon_base::TOUCH_ICON
, helper
.current_candidate()->icon_type
);
1004 // Whether new icon is requested from history
1005 history_handler
= helper
.history_handler();
1006 ASSERT_TRUE(history_handler
);
1007 EXPECT_EQ(latest_icon_url
, history_handler
->icon_url_
);
1008 EXPECT_EQ(favicon_base::TOUCH_ICON
, history_handler
->icon_type_
);
1009 EXPECT_EQ(page_url
, history_handler
->page_url_
);
1011 // Reset the history_handler to verify whether favicon is request from
1013 // Save the callback for late use.
1014 favicon_base::FaviconResultsCallback callback
= history_handler
->callback_
;
1015 helper
.set_history_handler(nullptr);
1017 // Simulates download succeed.
1018 download_handler
->InvokeCallback();
1019 // The downloaded icon should be thrown away as there is favicon update.
1020 EXPECT_FALSE(helper
.history_handler());
1022 download_handler
->Reset();
1024 // Simulates getting the icon from history.
1025 scoped_ptr
<HistoryRequestHandler
> handler
;
1026 handler
.reset(new HistoryRequestHandler(
1027 page_url
, latest_icon_url
, favicon_base::TOUCH_ICON
, callback
));
1028 SetFaviconRawBitmapResult(latest_icon_url
,
1029 favicon_base::TOUCH_ICON
,
1030 false /* expired */,
1031 &handler
->history_results_
);
1032 handler
->InvokeCallback();
1034 // No download request.
1035 EXPECT_FALSE(download_handler
->HasDownload());
1038 #if !defined(OS_ANDROID)
1040 // Test the favicon which is selected when the web page provides several
1041 // favicons and none of the favicons are cached in history.
1042 // The goal of this test is to be more of an integration test than
1043 // SelectFaviconFramesTest.*.
1044 TEST_F(FaviconHandlerTest
, MultipleFavicons
) {
1045 const GURL
kPageURL("http://www.google.com");
1046 const FaviconURL kSourceIconURLs
[] = {
1047 FaviconURL(GURL("http://www.google.com/a"),
1048 favicon_base::FAVICON
,
1049 std::vector
<gfx::Size
>()),
1050 FaviconURL(GURL("http://www.google.com/b"),
1051 favicon_base::FAVICON
,
1052 std::vector
<gfx::Size
>()),
1053 FaviconURL(GURL("http://www.google.com/c"),
1054 favicon_base::FAVICON
,
1055 std::vector
<gfx::Size
>()),
1056 FaviconURL(GURL("http://www.google.com/d"),
1057 favicon_base::FAVICON
,
1058 std::vector
<gfx::Size
>()),
1059 FaviconURL(GURL("http://www.google.com/e"),
1060 favicon_base::FAVICON
,
1061 std::vector
<gfx::Size
>())};
1063 // Set the supported scale factors to 1x and 2x. This affects the behavior of
1064 // SelectFaviconFrames().
1065 std::vector
<ui::ScaleFactor
> scale_factors
;
1066 scale_factors
.push_back(ui::SCALE_FACTOR_100P
);
1067 scale_factors
.push_back(ui::SCALE_FACTOR_200P
);
1068 ui::test::ScopedSetSupportedScaleFactors
scoped_supported(scale_factors
);
1070 // 1) Test that if there are several single resolution favicons to choose from
1071 // that the largest exact match is chosen.
1072 TestFaviconDriver driver1
;
1073 TestFaviconHandler
handler1(kPageURL
, &driver1
,
1074 favicon::FaviconHandler::FAVICON
, false);
1076 const int kSizes1
[] = { 16, 24, 32, 48, 256 };
1077 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1078 kSourceIconURLs
+ arraysize(kSizes1
));
1079 DownloadTillDoneIgnoringHistory(
1080 &driver1
, &handler1
, kPageURL
, urls1
, kSizes1
);
1082 EXPECT_EQ(0u, handler1
.image_urls().size());
1083 EXPECT_TRUE(driver1
.GetActiveFaviconValidity());
1084 EXPECT_FALSE(driver1
.GetActiveFaviconImage().IsEmpty());
1085 EXPECT_EQ(gfx::kFaviconSize
, driver1
.GetActiveFaviconImage().Width());
1087 size_t expected_index
= 2u;
1088 EXPECT_EQ(32, kSizes1
[expected_index
]);
1089 EXPECT_EQ(kSourceIconURLs
[expected_index
].icon_url
,
1090 driver1
.GetActiveFaviconURL());
1092 // 2) Test that if there are several single resolution favicons to choose
1093 // from, the exact match is preferred even if it results in upsampling.
1094 TestFaviconDriver driver2
;
1095 TestFaviconHandler
handler2(kPageURL
, &driver2
,
1096 favicon::FaviconHandler::FAVICON
, false);
1098 const int kSizes2
[] = { 16, 24, 48, 256 };
1099 std::vector
<FaviconURL
> urls2(kSourceIconURLs
,
1100 kSourceIconURLs
+ arraysize(kSizes2
));
1101 DownloadTillDoneIgnoringHistory(
1102 &driver2
, &handler2
, kPageURL
, urls2
, kSizes2
);
1103 EXPECT_TRUE(driver2
.GetActiveFaviconValidity());
1104 expected_index
= 0u;
1105 EXPECT_EQ(16, kSizes2
[expected_index
]);
1106 EXPECT_EQ(kSourceIconURLs
[expected_index
].icon_url
,
1107 driver2
.GetActiveFaviconURL());
1109 // 3) Test that favicons which need to be upsampled a little or downsampled
1110 // a little are preferred over huge favicons.
1111 TestFaviconDriver driver3
;
1112 TestFaviconHandler
handler3(kPageURL
, &driver3
,
1113 favicon::FaviconHandler::FAVICON
, false);
1115 const int kSizes3
[] = { 256, 48 };
1116 std::vector
<FaviconURL
> urls3(kSourceIconURLs
,
1117 kSourceIconURLs
+ arraysize(kSizes3
));
1118 DownloadTillDoneIgnoringHistory(
1119 &driver3
, &handler3
, kPageURL
, urls3
, kSizes3
);
1120 EXPECT_TRUE(driver3
.GetActiveFaviconValidity());
1121 expected_index
= 1u;
1122 EXPECT_EQ(48, kSizes3
[expected_index
]);
1123 EXPECT_EQ(kSourceIconURLs
[expected_index
].icon_url
,
1124 driver3
.GetActiveFaviconURL());
1126 TestFaviconDriver driver4
;
1127 TestFaviconHandler
handler4(kPageURL
, &driver4
,
1128 favicon::FaviconHandler::FAVICON
, false);
1130 const int kSizes4
[] = { 17, 256 };
1131 std::vector
<FaviconURL
> urls4(kSourceIconURLs
,
1132 kSourceIconURLs
+ arraysize(kSizes4
));
1133 DownloadTillDoneIgnoringHistory(
1134 &driver4
, &handler4
, kPageURL
, urls4
, kSizes4
);
1135 EXPECT_TRUE(driver4
.GetActiveFaviconValidity());
1136 expected_index
= 0u;
1137 EXPECT_EQ(17, kSizes4
[expected_index
]);
1138 EXPECT_EQ(kSourceIconURLs
[expected_index
].icon_url
,
1139 driver4
.GetActiveFaviconURL());
1144 TEST_F(FaviconHandlerTest
, TestSortFavicon
) {
1145 const GURL
kPageURL("http://www.google.com");
1146 std::vector
<gfx::Size
> icon1
;
1147 icon1
.push_back(gfx::Size(1024, 1024));
1148 icon1
.push_back(gfx::Size(512, 512));
1150 std::vector
<gfx::Size
> icon2
;
1151 icon2
.push_back(gfx::Size(15, 15));
1152 icon2
.push_back(gfx::Size(16, 16));
1154 std::vector
<gfx::Size
> icon3
;
1155 icon3
.push_back(gfx::Size(16, 16));
1156 icon3
.push_back(gfx::Size(14, 14));
1158 const FaviconURL kSourceIconURLs
[] = {
1159 FaviconURL(GURL("http://www.google.com/a"), favicon_base::FAVICON
, icon1
),
1160 FaviconURL(GURL("http://www.google.com/b"), favicon_base::FAVICON
, icon2
),
1161 FaviconURL(GURL("http://www.google.com/c"), favicon_base::FAVICON
, icon3
),
1162 FaviconURL(GURL("http://www.google.com/d"),
1163 favicon_base::FAVICON
,
1164 std::vector
<gfx::Size
>()),
1165 FaviconURL(GURL("http://www.google.com/e"),
1166 favicon_base::FAVICON
,
1167 std::vector
<gfx::Size
>())};
1169 TestFaviconDriver driver1
;
1170 TestFaviconHandler
handler1(kPageURL
, &driver1
,
1171 favicon::FaviconHandler::FAVICON
, true);
1172 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1173 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1174 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1176 struct ExpectedResult
{
1177 // The favicon's index in kSourceIconURLs.
1178 size_t favicon_index
;
1179 // Width of largest bitmap.
1182 // First is icon1, though its size larger than maximal.
1185 // The 16x16 is largest.
1187 // Third is icon3 though it has same size as icon2.
1188 // The 16x16 is largest.
1190 // The rest of bitmaps come in order, there is no sizes attribute.
1194 const std::vector
<FaviconURL
>& icons
= handler1
.image_urls();
1195 ASSERT_EQ(5u, icons
.size());
1196 for (size_t i
= 0; i
< icons
.size(); ++i
) {
1197 EXPECT_EQ(kSourceIconURLs
[results
[i
].favicon_index
].icon_url
,
1199 if (results
[i
].width
!= -1)
1200 EXPECT_EQ(results
[i
].width
, icons
[i
].icon_sizes
[0].width());
1204 TEST_F(FaviconHandlerTest
, TestDownloadLargestFavicon
) {
1205 const GURL
kPageURL("http://www.google.com");
1206 std::vector
<gfx::Size
> icon1
;
1207 icon1
.push_back(gfx::Size(1024, 1024));
1208 icon1
.push_back(gfx::Size(512, 512));
1210 std::vector
<gfx::Size
> icon2
;
1211 icon2
.push_back(gfx::Size(15, 15));
1212 icon2
.push_back(gfx::Size(14, 14));
1214 std::vector
<gfx::Size
> icon3
;
1215 icon3
.push_back(gfx::Size(16, 16));
1216 icon3
.push_back(gfx::Size(512, 512));
1218 const FaviconURL kSourceIconURLs
[] = {
1220 GURL("http://www.google.com/a"), favicon_base::FAVICON
, icon1
),
1222 GURL("http://www.google.com/b"), favicon_base::FAVICON
, icon2
),
1224 GURL("http://www.google.com/c"), favicon_base::FAVICON
, icon3
),
1225 FaviconURL(GURL("http://www.google.com/d"),
1226 favicon_base::FAVICON
,
1227 std::vector
<gfx::Size
>()),
1228 FaviconURL(GURL("http://www.google.com/e"),
1229 favicon_base::FAVICON
,
1230 std::vector
<gfx::Size
>())};
1232 TestFaviconDriver driver1
;
1233 TestFaviconHandler
handler1(kPageURL
, &driver1
,
1234 favicon::FaviconHandler::FAVICON
, true);
1235 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1236 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1237 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1239 // Simulate the download failed, to check whether the icons were requested
1240 // to download according their size.
1241 struct ExpectedResult
{
1242 // The size of image_urls_.
1243 size_t image_urls_size
;
1244 // The favicon's index in kSourceIconURLs.
1245 size_t favicon_index
;
1246 // Width of largest bitmap.
1252 // The rest of bitmaps come in order.
1257 for (int i
= 0; i
< 5; ++i
) {
1258 ASSERT_EQ(results
[i
].image_urls_size
, handler1
.image_urls().size());
1259 EXPECT_EQ(kSourceIconURLs
[results
[i
].favicon_index
].icon_url
,
1260 handler1
.current_candidate()->icon_url
);
1261 if (results
[i
].width
!= -1) {
1262 EXPECT_EQ(results
[i
].width
, handler1
.current_candidate()->
1263 icon_sizes
[0].width());
1266 // Simulate no favicon from history.
1267 handler1
.history_handler()->history_results_
.clear();
1268 handler1
.history_handler()->InvokeCallback();
1270 // Verify download request
1271 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1272 EXPECT_EQ(kSourceIconURLs
[results
[i
].favicon_index
].icon_url
,
1273 handler1
.download_handler()->GetImageUrl());
1275 // Simulate the download failed.
1276 handler1
.download_handler()->set_failed(true);
1277 handler1
.download_handler()->InvokeCallback();
1281 TEST_F(FaviconHandlerTest
, TestSelectLargestFavicon
) {
1282 const GURL
kPageURL("http://www.google.com");
1284 std::vector
<gfx::Size
> one_icon
;
1285 one_icon
.push_back(gfx::Size(15, 15));
1287 std::vector
<gfx::Size
> two_icons
;
1288 two_icons
.push_back(gfx::Size(14, 14));
1289 two_icons
.push_back(gfx::Size(16, 16));
1291 const FaviconURL kSourceIconURLs
[] = {
1293 GURL("http://www.google.com/b"), favicon_base::FAVICON
, one_icon
),
1295 GURL("http://www.google.com/c"), favicon_base::FAVICON
, two_icons
)};
1297 TestFaviconDriver driver1
;
1298 TestFaviconHandler
handler1(kPageURL
, &driver1
,
1299 favicon::FaviconHandler::FAVICON
, true);
1300 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1301 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1302 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1304 ASSERT_EQ(2u, handler1
.urls().size());
1306 // Index of largest favicon in kSourceIconURLs.
1308 // The largest bitmap's index in Favicon .
1311 // Verify the icon_bitmaps_ was initialized correctly.
1312 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
,
1313 handler1
.current_candidate()->icon_url
);
1314 EXPECT_EQ(kSourceIconURLs
[i
].icon_sizes
[b
],
1315 handler1
.current_candidate()->icon_sizes
[0]);
1317 // Simulate no favicon from history.
1318 handler1
.history_handler()->history_results_
.clear();
1319 handler1
.history_handler()->InvokeCallback();
1321 // Verify download request
1322 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1323 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
,
1324 handler1
.download_handler()->GetImageUrl());
1326 // Give the correct download result.
1327 std::vector
<int> sizes
;
1328 for (std::vector
<gfx::Size
>::const_iterator j
=
1329 kSourceIconURLs
[i
].icon_sizes
.begin();
1330 j
!= kSourceIconURLs
[i
].icon_sizes
.end(); ++j
)
1331 sizes
.push_back(j
->width());
1333 handler1
.download_handler()->SetImageSizes(sizes
);
1334 handler1
.download_handler()->InvokeCallback();
1336 // Verify the largest bitmap has been saved into history.
1337 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
, handler1
.history_handler()->icon_url_
);
1338 EXPECT_EQ(kSourceIconURLs
[i
].icon_sizes
[b
],
1339 handler1
.history_handler()->size_
);
1340 // Verify NotifyFaviconAvailable().
1341 EXPECT_FALSE(driver1
.update_active_favicon());
1342 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
, driver1
.available_icon_url());
1343 EXPECT_EQ(kSourceIconURLs
[i
].icon_sizes
[b
],
1344 driver1
.available_favicon().Size());
1347 TEST_F(FaviconHandlerTest
, TestFaviconWasScaledAfterDownload
) {
1348 const GURL
kPageURL("http://www.google.com");
1349 const int kMaximalSize
=
1350 TestFaviconHandler::GetMaximalIconSize(favicon_base::FAVICON
);
1352 std::vector
<gfx::Size
> icon1
;
1353 icon1
.push_back(gfx::Size(kMaximalSize
+ 1, kMaximalSize
+ 1));
1355 std::vector
<gfx::Size
> icon2
;
1356 icon2
.push_back(gfx::Size(kMaximalSize
+ 2, kMaximalSize
+ 2));
1358 const FaviconURL kSourceIconURLs
[] = {
1360 GURL("http://www.google.com/b"), favicon_base::FAVICON
, icon1
),
1362 GURL("http://www.google.com/c"), favicon_base::FAVICON
, icon2
)};
1364 TestFaviconDriver driver1
;
1365 TestFaviconHandler
handler1(kPageURL
, &driver1
,
1366 favicon::FaviconHandler::FAVICON
, true);
1367 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1368 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1369 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1371 ASSERT_EQ(2u, handler1
.urls().size());
1373 // Index of largest favicon in kSourceIconURLs.
1375 // The largest bitmap's index in Favicon .
1378 // Verify the icon_bitmaps_ was initialized correctly.
1379 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
,
1380 handler1
.current_candidate()->icon_url
);
1381 EXPECT_EQ(kSourceIconURLs
[i
].icon_sizes
[b
],
1382 handler1
.current_candidate()->icon_sizes
[0]);
1384 // Simulate no favicon from history.
1385 handler1
.history_handler()->history_results_
.clear();
1386 handler1
.history_handler()->InvokeCallback();
1388 // Verify download request
1389 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1390 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
,
1391 handler1
.download_handler()->GetImageUrl());
1393 // Give the scaled download bitmap.
1394 std::vector
<int> sizes
;
1395 sizes
.push_back(kMaximalSize
);
1397 handler1
.download_handler()->SetImageSizes(sizes
);
1398 handler1
.download_handler()->InvokeCallback();
1400 // Verify the largest bitmap has been saved into history though it was
1401 // scaled down to maximal size and smaller than icon1 now.
1402 EXPECT_EQ(kSourceIconURLs
[i
].icon_url
, handler1
.history_handler()->icon_url_
);
1403 EXPECT_EQ(gfx::Size(kMaximalSize
, kMaximalSize
),
1404 handler1
.history_handler()->size_
);
1407 TEST_F(FaviconHandlerTest
, TestKeepDownloadedLargestFavicon
) {
1408 const GURL
kPageURL("http://www.google.com");
1410 std::vector
<gfx::Size
> icon1
;
1411 icon1
.push_back(gfx::Size(16, 16));
1412 const int actual_size1
= 10;
1414 std::vector
<gfx::Size
> icon2
;
1415 icon2
.push_back(gfx::Size(15, 15));
1416 const int actual_size2
= 12;
1418 const FaviconURL kSourceIconURLs
[] = {
1419 FaviconURL(GURL("http://www.google.com/b"), favicon_base::FAVICON
, icon1
),
1420 FaviconURL(GURL("http://www.google.com/c"), favicon_base::FAVICON
, icon2
),
1421 FaviconURL(GURL("http://www.google.com/d"),
1422 favicon_base::FAVICON
,
1423 std::vector
<gfx::Size
>())};
1425 TestFaviconDriver driver1
;
1426 TestFaviconHandler
handler1(kPageURL
, &driver1
,
1427 favicon::FaviconHandler::FAVICON
, true);
1428 std::vector
<FaviconURL
> urls1(kSourceIconURLs
,
1429 kSourceIconURLs
+ arraysize(kSourceIconURLs
));
1430 UpdateFaviconURL(&driver1
, &handler1
, kPageURL
, urls1
);
1431 ASSERT_EQ(3u, handler1
.urls().size());
1433 // Simulate no favicon from history.
1434 handler1
.history_handler()->history_results_
.clear();
1435 handler1
.history_handler()->InvokeCallback();
1437 // Verify the first icon was request to download
1438 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1439 EXPECT_EQ(kSourceIconURLs
[0].icon_url
,
1440 handler1
.download_handler()->GetImageUrl());
1442 // Give the incorrect size.
1443 std::vector
<int> sizes
;
1444 sizes
.push_back(actual_size1
);
1445 handler1
.download_handler()->SetImageSizes(sizes
);
1446 handler1
.download_handler()->InvokeCallback();
1448 // Simulate no favicon from history.
1449 handler1
.history_handler()->history_results_
.clear();
1450 handler1
.history_handler()->InvokeCallback();
1452 // Verify the 2nd icon was request to download
1453 ASSERT_TRUE(handler1
.download_handler()->HasDownload());
1454 EXPECT_EQ(kSourceIconURLs
[1].icon_url
,
1455 handler1
.download_handler()->GetImageUrl());
1457 // Very the best candidate is icon1
1458 EXPECT_EQ(kSourceIconURLs
[0].icon_url
,
1459 handler1
.best_favicon_candidate().image_url
);
1460 EXPECT_EQ(gfx::Size(actual_size1
, actual_size1
),
1461 handler1
.best_favicon_candidate().image
.Size());
1463 // Give the incorrect size.
1465 sizes
.push_back(actual_size2
);
1466 handler1
.download_handler()->SetImageSizes(sizes
);
1467 handler1
.download_handler()->InvokeCallback();
1469 // Verify icon2 has been saved into history.
1470 EXPECT_EQ(kSourceIconURLs
[1].icon_url
, handler1
.history_handler()->icon_url_
);
1471 EXPECT_EQ(gfx::Size(actual_size2
, actual_size2
),
1472 handler1
.history_handler()->size_
);
1475 static KeyedService
* BuildFaviconService(content::BrowserContext
* context
) {
1476 Profile
* profile
= Profile::FromBrowserContext(context
);
1477 return new favicon::FaviconService(
1478 ChromeFaviconClientFactory::GetForProfile(profile
),
1479 HistoryServiceFactory::GetForProfile(profile
,
1480 ServiceAccessType::EXPLICIT_ACCESS
));
1483 static KeyedService
* BuildHistoryService(content::BrowserContext
* context
) {
1487 // Test that Favicon is not requested repeatedly during the same session if
1488 // server returns HTTP 404 status.
1489 TEST_F(FaviconHandlerTest
, UnableToDownloadFavicon
) {
1490 const GURL
missing_icon_url("http://www.google.com/favicon.ico");
1491 const GURL
another_icon_url("http://www.youtube.com/favicon.ico");
1493 Profile
* profile
= Profile::FromBrowserContext(
1494 web_contents()->GetBrowserContext());
1496 FaviconServiceFactory::GetInstance()->SetTestingFactory(
1497 profile
, BuildFaviconService
);
1499 HistoryServiceFactory::GetInstance()->SetTestingFactory(
1500 profile
, BuildHistoryService
);
1502 favicon::FaviconService
* favicon_service
=
1503 FaviconServiceFactory::GetForProfile(profile
,
1504 ServiceAccessType::IMPLICIT_ACCESS
);
1506 FaviconTabHelper::CreateForWebContents(web_contents());
1507 FaviconTabHelper
* favicon_tab_helper
=
1508 FaviconTabHelper::FromWebContents(web_contents());
1510 std::vector
<SkBitmap
> empty_icons
;
1511 std::vector
<gfx::Size
> empty_icon_sizes
;
1512 int download_id
= 0;
1514 // Try to download missing icon.
1515 download_id
= favicon_tab_helper
->StartDownload(missing_icon_url
, 0);
1516 EXPECT_NE(0, download_id
);
1517 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1519 // Report download failure with HTTP 503 status.
1520 favicon_tab_helper
->DidDownloadFavicon(download_id
, 503, missing_icon_url
,
1521 empty_icons
, empty_icon_sizes
);
1522 // Icon is not marked as UnableToDownload as HTTP status is not 404.
1523 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1525 // Try to download again.
1526 download_id
= favicon_tab_helper
->StartDownload(missing_icon_url
, 0);
1527 EXPECT_NE(0, download_id
);
1528 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1530 // Report download failure with HTTP 404 status.
1531 favicon_tab_helper
->DidDownloadFavicon(download_id
, 404, missing_icon_url
,
1532 empty_icons
, empty_icon_sizes
);
1533 // Icon is marked as UnableToDownload.
1534 EXPECT_TRUE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1536 // Try to download again.
1537 download_id
= favicon_tab_helper
->StartDownload(missing_icon_url
, 0);
1538 // Download is not started and Icon is still marked as UnableToDownload.
1539 EXPECT_EQ(0, download_id
);
1540 EXPECT_TRUE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1542 // Try to download another icon.
1543 download_id
= favicon_tab_helper
->StartDownload(another_icon_url
, 0);
1544 // Download is started as another icon URL is not same as missing_icon_url.
1545 EXPECT_NE(0, download_id
);
1546 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(another_icon_url
));
1548 // Clear the list of missing icons.
1549 favicon_service
->ClearUnableToDownloadFavicons();
1550 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1551 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(another_icon_url
));
1553 // Try to download again.
1554 download_id
= favicon_tab_helper
->StartDownload(missing_icon_url
, 0);
1555 EXPECT_NE(0, download_id
);
1556 // Report download success with HTTP 200 status.
1557 favicon_tab_helper
->DidDownloadFavicon(download_id
, 200, missing_icon_url
,
1558 empty_icons
, empty_icon_sizes
);
1559 // Icon is not marked as UnableToDownload as HTTP status is not 404.
1560 EXPECT_FALSE(favicon_service
->WasUnableToDownloadFavicon(missing_icon_url
));
1563 class FaviconHandlerActiveFaviconValidityParamTest
:
1564 public FaviconHandlerTest
,
1565 public ::testing::WithParamInterface
<bool> {
1567 FaviconHandlerActiveFaviconValidityParamTest() {}
1569 ~FaviconHandlerActiveFaviconValidityParamTest() override
{}
1571 bool GetActiveFaviconValiditySetting() {
1576 DISALLOW_COPY_AND_ASSIGN(FaviconHandlerActiveFaviconValidityParamTest
);
1579 TEST_P(FaviconHandlerActiveFaviconValidityParamTest
,
1580 TestDownloadLargestIconDoesNotImpactActiveFaviconValidity
) {
1581 const GURL
page_url("http://www.google.com");
1583 std::vector
<gfx::Size
> one_icon
;
1584 one_icon
.push_back(gfx::Size(15, 15));
1586 const GURL
old_favicon_url("http://www.google.com/old");
1587 const GURL
new_favicon_url("http://www.google.com/b");
1588 const FaviconURL source_icon_urls
[] = {
1589 FaviconURL(new_favicon_url
, favicon_base::FAVICON
, one_icon
)};
1590 TestFaviconDriver driver1
;
1591 TestFaviconHandler
handler1(page_url
, &driver1
,
1592 favicon::FaviconHandler::FAVICON
, true);
1593 std::vector
<FaviconURL
> urls1(source_icon_urls
,
1594 source_icon_urls
+ arraysize(source_icon_urls
));
1595 UpdateFaviconURL(&driver1
, &handler1
, page_url
, urls1
);
1597 HistoryRequestHandler
* history_handler
= handler1
.history_handler();
1599 // Simulate the active favicon is updated, this shouldn't happen in real
1600 // use case, but we want to verify the behavior below is not impacted by
1602 driver1
.SetActiveFaviconValidity(GetActiveFaviconValiditySetting());
1603 // Simulate the get favicon from history, but favicon URL didn't match.
1604 SetFaviconRawBitmapResult(old_favicon_url
,
1605 &history_handler
->history_results_
);
1606 history_handler
->InvokeCallback();
1607 // Since we downloaded largest icon, and don't want to set active favicon
1608 // NotifyFaviconAvaliable() should be called with is_active_favicon as false.
1609 EXPECT_EQ(old_favicon_url
, driver1
.available_icon_url());
1610 EXPECT_FALSE(driver1
.update_active_favicon());
1611 EXPECT_EQ(1u, driver1
.num_favicon_available());
1613 // We are trying to get favicon from history again.
1614 history_handler
= handler1
.history_handler();
1615 EXPECT_EQ(new_favicon_url
, history_handler
->icon_url_
);
1616 // Simulate the get expired favicon from history.
1617 history_handler
->history_results_
.clear();
1618 SetFaviconRawBitmapResult(new_favicon_url
, favicon_base::FAVICON
, true,
1619 &history_handler
->history_results_
);
1620 history_handler
->InvokeCallback();
1621 // Since we downloaded largest icon, and don't want to set active favicon
1622 // NotifyFaviconAvaliable() should be called with is_active_favicon as false.
1623 EXPECT_EQ(new_favicon_url
, driver1
.available_icon_url());
1624 EXPECT_FALSE(driver1
.update_active_favicon());
1625 EXPECT_EQ(2u, driver1
.num_favicon_available());
1627 // We are trying to download favicon.
1628 DownloadHandler
* download_handler
= handler1
.download_handler();
1629 EXPECT_TRUE(download_handler
->HasDownload());
1630 EXPECT_EQ(new_favicon_url
, download_handler
->GetImageUrl());
1631 // Simulate the download succeed.
1632 download_handler
->InvokeCallback();
1633 // Since we downloaded largest icon, and don't want to set active favicon
1634 // NotifyFaviconAvaliable() should be called with is_active_favicon as false.
1635 EXPECT_EQ(new_favicon_url
, driver1
.available_icon_url());
1636 EXPECT_FALSE(driver1
.update_active_favicon());
1637 EXPECT_EQ(3u, driver1
.num_favicon_available());
1640 INSTANTIATE_TEST_CASE_P(FaviconHandlerTestActiveFaviconValidityTrueOrFalse
,
1641 FaviconHandlerActiveFaviconValidityParamTest
,