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