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