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_factory.h" 8 #include "chrome/browser/history/history_service_factory.h" 9 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 11 #include "content/public/browser/favicon_status.h" 12 #include "content/public/browser/invalidate_type.h" 13 #include "content/public/browser/navigation_entry.h" 14 #include "content/public/browser/web_contents.h" 15 #include "third_party/skia/include/core/SkBitmap.h" 16 #include "ui/gfx/codec/png_codec.h" 17 #include "ui/gfx/favicon_size.h" 18 #include "ui/gfx/image/image.h" 19 20 class TestFaviconHandler; 21 22 using content::FaviconURL; 23 using content::NavigationEntry; 24 using content::WebContents; 25 26 namespace { 27 28 // Fill the given bmp with valid png data. 29 void FillDataToBitmap(int w, int h, SkBitmap* bmp) { 30 bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h); 31 bmp->allocPixels(); 32 33 unsigned char* src_data = 34 reinterpret_cast<unsigned char*>(bmp->getAddr32(0, 0)); 35 for (int i = 0; i < w * h; i++) { 36 src_data[i * 4 + 0] = static_cast<unsigned char>(i % 255); 37 src_data[i * 4 + 1] = static_cast<unsigned char>(i % 255); 38 src_data[i * 4 + 2] = static_cast<unsigned char>(i % 255); 39 src_data[i * 4 + 3] = static_cast<unsigned char>(i % 255); 40 } 41 } 42 43 // Fill the given data buffer with valid png data. 44 void FillBitmap(int w, int h, std::vector<unsigned char>* output) { 45 SkBitmap bitmap; 46 FillDataToBitmap(w, h, &bitmap); 47 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, output); 48 } 49 50 void SetFaviconBitmapResult( 51 const GURL& icon_url, 52 chrome::IconType icon_type, 53 bool expired, 54 std::vector<chrome::FaviconBitmapResult>* favicon_bitmap_results) { 55 scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); 56 FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data()); 57 chrome::FaviconBitmapResult bitmap_result; 58 bitmap_result.expired = expired; 59 bitmap_result.bitmap_data = data; 60 // Use a pixel size other than (0,0) as (0,0) has a special meaning. 61 bitmap_result.pixel_size = gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize); 62 bitmap_result.icon_type = icon_type; 63 bitmap_result.icon_url = icon_url; 64 65 favicon_bitmap_results->push_back(bitmap_result); 66 } 67 68 void SetFaviconBitmapResult( 69 const GURL& icon_url, 70 std::vector<chrome::FaviconBitmapResult>* favicon_bitmap_results) { 71 SetFaviconBitmapResult(icon_url, chrome::FAVICON, 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 int image_size, 96 int max_image_size) { 97 download_.reset(new Download( 98 download_id, image_url, image_size, 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 SetImageSize(int size) { download_->image_size = size; } 108 109 private: 110 struct Download { 111 Download(int id, GURL url, int size, int max_size, bool failed) 112 : download_id(id), 113 image_url(url), 114 image_size(size), 115 max_image_size(max_size) {} 116 ~Download() {} 117 int download_id; 118 GURL image_url; 119 int image_size; 120 int max_image_size; 121 }; 122 123 TestFaviconHandler* favicon_helper_; 124 scoped_ptr<Download> download_; 125 bool failed_; 126 127 DISALLOW_COPY_AND_ASSIGN(DownloadHandler); 128 }; 129 130 // This class is used to save the history request for verifying with test case. 131 // It also will be used to simulate the history response. 132 class HistoryRequestHandler { 133 public: 134 HistoryRequestHandler(const GURL& page_url, 135 const GURL& icon_url, 136 int icon_type, 137 const FaviconService::FaviconResultsCallback& callback) 138 : page_url_(page_url), 139 icon_url_(icon_url), 140 icon_type_(icon_type), 141 callback_(callback) { 142 } 143 144 HistoryRequestHandler(const GURL& page_url, 145 const GURL& icon_url, 146 int icon_type, 147 const std::vector<unsigned char>& bitmap_data) 148 : page_url_(page_url), 149 icon_url_(icon_url), 150 icon_type_(icon_type), 151 bitmap_data_(bitmap_data) { 152 } 153 154 virtual ~HistoryRequestHandler() {} 155 void InvokeCallback(); 156 157 const GURL page_url_; 158 const GURL icon_url_; 159 const int icon_type_; 160 const std::vector<unsigned char> bitmap_data_; 161 std::vector<chrome::FaviconBitmapResult> history_results_; 162 FaviconService::FaviconResultsCallback callback_; 163 164 private: 165 DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler); 166 }; 167 168 } // namespace 169 170 171 class TestFaviconHandlerDelegate : public FaviconHandlerDelegate { 172 public: 173 TestFaviconHandlerDelegate() { 174 } 175 176 virtual ~TestFaviconHandlerDelegate() { 177 } 178 179 virtual NavigationEntry* GetActiveEntry() OVERRIDE { 180 ADD_FAILURE() << "TestFaviconHandlerDelegate::GetActiveEntry() " 181 << "should never be called in tests."; 182 return NULL; 183 } 184 185 virtual int StartDownload(const GURL& url, 186 int max_bitmap_size) OVERRIDE { 187 ADD_FAILURE() << "TestFaviconHandlerDelegate::StartDownload() " 188 << "should never be called in tests."; 189 return -1; 190 } 191 192 virtual void NotifyFaviconUpdated(bool icon_url_changed) OVERRIDE { 193 ADD_FAILURE() << "TestFaviconHandlerDelegate::NotifyFaviconUpdated() " 194 << "should never be called in tests."; 195 } 196 197 private: 198 DISALLOW_COPY_AND_ASSIGN(TestFaviconHandlerDelegate); 199 }; 200 201 // This class is used to catch the FaviconHandler's download and history 202 // request, and also provide the methods to access the FaviconHandler 203 // internals. 204 class TestFaviconHandler : public FaviconHandler { 205 public: 206 TestFaviconHandler(const GURL& page_url, 207 Profile* profile, 208 FaviconHandlerDelegate* delegate, 209 Type type) 210 : FaviconHandler(profile, delegate, type), 211 entry_(NavigationEntry::Create()), 212 download_id_(0), 213 num_favicon_updates_(0) { 214 entry_->SetURL(page_url); 215 download_handler_.reset(new DownloadHandler(this)); 216 } 217 218 virtual ~TestFaviconHandler() { 219 } 220 221 HistoryRequestHandler* history_handler() { 222 return history_handler_.get(); 223 } 224 225 // This method will take the ownership of the given handler. 226 void set_history_handler(HistoryRequestHandler* handler) { 227 history_handler_.reset(handler); 228 } 229 230 DownloadHandler* download_handler() { 231 return download_handler_.get(); 232 } 233 234 size_t num_favicon_update_notifications() const { 235 return num_favicon_updates_; 236 } 237 238 void ResetNumFaviconUpdateNotifications() { 239 num_favicon_updates_ = 0; 240 } 241 242 // Methods to access favicon internals. 243 virtual NavigationEntry* GetEntry() OVERRIDE { 244 return entry_.get(); 245 } 246 247 const std::deque<FaviconURL>& urls() { 248 return image_urls_; 249 } 250 251 FaviconURL* current_candidate() { 252 return FaviconHandler::current_candidate(); 253 } 254 255 protected: 256 virtual void UpdateFaviconMappingAndFetch( 257 const GURL& page_url, 258 const GURL& icon_url, 259 chrome::IconType icon_type, 260 const FaviconService::FaviconResultsCallback& callback, 261 CancelableTaskTracker* tracker) OVERRIDE { 262 history_handler_.reset(new HistoryRequestHandler(page_url, icon_url, 263 icon_type, callback)); 264 } 265 266 virtual void GetFavicon( 267 const GURL& icon_url, 268 chrome::IconType icon_type, 269 const FaviconService::FaviconResultsCallback& callback, 270 CancelableTaskTracker* tracker) OVERRIDE { 271 history_handler_.reset(new HistoryRequestHandler(GURL(), icon_url, 272 icon_type, callback)); 273 } 274 275 virtual void GetFaviconForURL( 276 const GURL& page_url, 277 int icon_types, 278 const FaviconService::FaviconResultsCallback& callback, 279 CancelableTaskTracker* tracker) OVERRIDE { 280 history_handler_.reset(new HistoryRequestHandler(page_url, GURL(), 281 icon_types, callback)); 282 } 283 284 virtual int DownloadFavicon(const GURL& image_url, 285 int max_bitmap_size) OVERRIDE { 286 download_id_++; 287 download_handler_->AddDownload( 288 download_id_, image_url, 0, max_bitmap_size); 289 return download_id_; 290 } 291 292 virtual void SetHistoryFavicons(const GURL& page_url, 293 const GURL& icon_url, 294 chrome::IconType icon_type, 295 const gfx::Image& image) OVERRIDE { 296 scoped_refptr<base::RefCountedMemory> bytes = image.As1xPNGBytes(); 297 std::vector<unsigned char> bitmap_data(bytes->front(), 298 bytes->front() + bytes->size()); 299 history_handler_.reset(new HistoryRequestHandler( 300 page_url, icon_url, icon_type, bitmap_data)); 301 } 302 303 virtual FaviconService* GetFaviconService() OVERRIDE { 304 // Just give none NULL value, so overridden methods can be hit. 305 return (FaviconService*)(1); 306 } 307 308 virtual bool ShouldSaveFavicon(const GURL& url) OVERRIDE { 309 return true; 310 } 311 312 virtual void NotifyFaviconUpdated(bool icon_url_changed) OVERRIDE { 313 ++num_favicon_updates_; 314 } 315 316 GURL page_url_; 317 318 private: 319 scoped_ptr<NavigationEntry> entry_; 320 321 // The unique id of a download request. It will be returned to a 322 // FaviconHandler. 323 int download_id_; 324 325 scoped_ptr<DownloadHandler> download_handler_; 326 scoped_ptr<HistoryRequestHandler> history_handler_; 327 328 // The number of times that NotifyFaviconUpdated() has been called. 329 size_t num_favicon_updates_; 330 331 DISALLOW_COPY_AND_ASSIGN(TestFaviconHandler); 332 }; 333 334 namespace { 335 336 void HistoryRequestHandler::InvokeCallback() { 337 if (!callback_.is_null()) { 338 callback_.Run(history_results_); 339 } 340 } 341 342 void DownloadHandler::InvokeCallback() { 343 int original_size = (download_->image_size > 0) ? 344 download_->image_size : gfx::kFaviconSize; 345 int downloaded_size = original_size; 346 if (download_->max_image_size != 0 && 347 downloaded_size > download_->max_image_size) { 348 downloaded_size = download_->max_image_size; 349 } 350 std::vector<SkBitmap> bitmaps; 351 std::vector<gfx::Size> original_bitmap_sizes; 352 if (!failed_) { 353 SkBitmap bitmap; 354 FillDataToBitmap(downloaded_size, downloaded_size, &bitmap); 355 bitmaps.push_back(bitmap); 356 original_bitmap_sizes.push_back(gfx::Size(original_size, original_size)); 357 } 358 favicon_helper_->OnDidDownloadFavicon(download_->download_id, 359 download_->image_url, 360 bitmaps, 361 original_bitmap_sizes); 362 } 363 364 class FaviconHandlerTest : public ChromeRenderViewHostTestHarness { 365 public: 366 FaviconHandlerTest() { 367 } 368 369 virtual ~FaviconHandlerTest() { 370 } 371 372 // Simulates requesting a favicon for |page_url| given: 373 // - We have not previously cached anything in history for |page_url| or for 374 // any of |candidates|. 375 // - The page provides favicons at |candidate_icons|. 376 // - The favicons at |candidate_icons| have edge pixel sizes of 377 // |candidate_icon_sizes|. 378 void DownloadTillDoneIgnoringHistory( 379 TestFaviconHandler* favicon_handler, 380 const GURL& page_url, 381 const std::vector<FaviconURL>& candidate_icons, 382 const int* candidate_icon_sizes) { 383 favicon_handler->ResetNumFaviconUpdateNotifications(); 384 385 favicon_handler->FetchFavicon(page_url); 386 favicon_handler->history_handler()->InvokeCallback(); 387 388 favicon_handler->OnUpdateFaviconURL(0, candidate_icons); 389 EXPECT_EQ(candidate_icons.size(), favicon_handler->image_urls().size()); 390 391 DownloadHandler* download_handler = favicon_handler->download_handler(); 392 for (size_t i = 0; i < candidate_icons.size(); ++i) { 393 favicon_handler->history_handler()->history_results_.clear(); 394 favicon_handler->history_handler()->InvokeCallback(); 395 ASSERT_TRUE(download_handler->HasDownload()); 396 EXPECT_EQ(download_handler->GetImageUrl(), 397 candidate_icons[i].icon_url); 398 download_handler->SetImageSize(candidate_icon_sizes[i]); 399 download_handler->InvokeCallback(); 400 401 if (favicon_handler->num_favicon_update_notifications()) 402 return; 403 } 404 } 405 406 virtual void SetUp() { 407 // The score computed by SelectFaviconFrames() is dependent on the supported 408 // scale factors of the platform. It is used for determining the goodness of 409 // a downloaded bitmap in FaviconHandler::OnDidDownloadFavicon(). 410 // Force the values of the scale factors so that the tests produce the same 411 // results on all platforms. 412 std::vector<ui::ScaleFactor> scale_factors; 413 scale_factors.push_back(ui::SCALE_FACTOR_100P); 414 scoped_set_supported_scale_factors_.reset( 415 new ui::test::ScopedSetSupportedScaleFactors(scale_factors)); 416 417 ChromeRenderViewHostTestHarness::SetUp(); 418 } 419 420 virtual void TearDown() OVERRIDE { 421 Profile* profile = Profile::FromBrowserContext( 422 web_contents()->GetBrowserContext()); 423 FaviconServiceFactory::GetInstance()->SetTestingFactory( 424 profile, NULL); 425 ChromeRenderViewHostTestHarness::TearDown(); 426 } 427 428 private: 429 typedef scoped_ptr<ui::test::ScopedSetSupportedScaleFactors> 430 ScopedSetSupportedScaleFactors; 431 ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_; 432 DISALLOW_COPY_AND_ASSIGN(FaviconHandlerTest); 433 }; 434 435 TEST_F(FaviconHandlerTest, GetFaviconFromHistory) { 436 const GURL page_url("http://www.google.com"); 437 const GURL icon_url("http://www.google.com/favicon"); 438 439 TestFaviconHandlerDelegate delegate; 440 Profile* profile = Profile::FromBrowserContext( 441 web_contents()->GetBrowserContext()); 442 TestFaviconHandler helper(page_url, profile, 443 &delegate, FaviconHandler::FAVICON); 444 445 helper.FetchFavicon(page_url); 446 HistoryRequestHandler* history_handler = helper.history_handler(); 447 // Ensure the data given to history is correct. 448 ASSERT_TRUE(history_handler); 449 EXPECT_EQ(page_url, history_handler->page_url_); 450 EXPECT_EQ(GURL(), history_handler->icon_url_); 451 EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_); 452 453 SetFaviconBitmapResult(icon_url, &history_handler->history_results_); 454 455 // Send history response. 456 history_handler->InvokeCallback(); 457 // Verify FaviconHandler status 458 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid); 459 EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url); 460 461 // Simulates update favicon url. 462 std::vector<FaviconURL> urls; 463 urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON)); 464 helper.OnUpdateFaviconURL(0, urls); 465 466 // Verify FaviconHandler status 467 EXPECT_EQ(1U, helper.urls().size()); 468 ASSERT_TRUE(helper.current_candidate()); 469 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); 470 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type); 471 472 // Favicon shouldn't request to download icon. 473 EXPECT_FALSE(helper.download_handler()->HasDownload()); 474 } 475 476 TEST_F(FaviconHandlerTest, DownloadFavicon) { 477 const GURL page_url("http://www.google.com"); 478 const GURL icon_url("http://www.google.com/favicon"); 479 480 TestFaviconHandlerDelegate delegate; 481 Profile* profile = Profile::FromBrowserContext( 482 web_contents()->GetBrowserContext()); 483 TestFaviconHandler helper(page_url, profile, 484 &delegate, FaviconHandler::FAVICON); 485 486 helper.FetchFavicon(page_url); 487 HistoryRequestHandler* history_handler = helper.history_handler(); 488 // Ensure the data given to history is correct. 489 ASSERT_TRUE(history_handler); 490 EXPECT_EQ(page_url, history_handler->page_url_); 491 EXPECT_EQ(GURL(), history_handler->icon_url_); 492 EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_); 493 494 // Set icon data expired 495 SetFaviconBitmapResult(icon_url, chrome::FAVICON, true /* expired */, 496 &history_handler->history_results_); 497 // Send history response. 498 history_handler->InvokeCallback(); 499 // Verify FaviconHandler status 500 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid); 501 EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url); 502 503 // Simulates update favicon url. 504 std::vector<FaviconURL> urls; 505 urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON)); 506 helper.OnUpdateFaviconURL(0, urls); 507 508 // Verify FaviconHandler status 509 EXPECT_EQ(1U, helper.urls().size()); 510 ASSERT_TRUE(helper.current_candidate()); 511 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); 512 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type); 513 514 // Favicon should request to download icon now. 515 DownloadHandler* download_handler = helper.download_handler(); 516 EXPECT_TRUE(helper.download_handler()->HasDownload()); 517 518 // Verify the download request. 519 EXPECT_EQ(icon_url, download_handler->GetImageUrl()); 520 521 // Reset the history_handler to verify whether favicon is set. 522 helper.set_history_handler(NULL); 523 524 // Smulates download done. 525 download_handler->InvokeCallback(); 526 527 // New icon should be saved to history backend and navigation entry. 528 history_handler = helper.history_handler(); 529 ASSERT_TRUE(history_handler); 530 EXPECT_EQ(icon_url, history_handler->icon_url_); 531 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); 532 EXPECT_LT(0U, history_handler->bitmap_data_.size()); 533 EXPECT_EQ(page_url, history_handler->page_url_); 534 535 // Verify NavigationEntry. 536 content::FaviconStatus favicon_status = helper.GetEntry()->GetFavicon(); 537 EXPECT_EQ(icon_url, favicon_status.url); 538 EXPECT_TRUE(favicon_status.valid); 539 EXPECT_FALSE(favicon_status.image.IsEmpty()); 540 EXPECT_EQ(gfx::kFaviconSize, favicon_status.image.Width()); 541 } 542 543 TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) { 544 const GURL page_url("http://www.google.com"); 545 const GURL icon_url("http://www.google.com/favicon"); 546 const GURL new_icon_url("http://www.google.com/new_favicon"); 547 548 TestFaviconHandlerDelegate delegate; 549 Profile* profile = Profile::FromBrowserContext( 550 web_contents()->GetBrowserContext()); 551 TestFaviconHandler helper(page_url, profile, 552 &delegate, FaviconHandler::FAVICON); 553 554 helper.FetchFavicon(page_url); 555 HistoryRequestHandler* history_handler = helper.history_handler(); 556 // Ensure the data given to history is correct. 557 ASSERT_TRUE(history_handler); 558 EXPECT_EQ(page_url, history_handler->page_url_); 559 EXPECT_EQ(GURL(), history_handler->icon_url_); 560 EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_); 561 562 // Set valid icon data. 563 SetFaviconBitmapResult(icon_url, &history_handler->history_results_); 564 565 // Send history response. 566 history_handler->InvokeCallback(); 567 // Verify FaviconHandler status. 568 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid); 569 EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url); 570 571 // Reset the history_handler to verify whether new icon is requested from 572 // history. 573 helper.set_history_handler(NULL); 574 575 // Simulates update with the different favicon url. 576 std::vector<FaviconURL> urls; 577 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON)); 578 helper.OnUpdateFaviconURL(0, urls); 579 580 // Verify FaviconHandler status. 581 EXPECT_EQ(1U, helper.urls().size()); 582 ASSERT_TRUE(helper.current_candidate()); 583 ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url); 584 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type); 585 586 // Favicon should be requested from history. 587 history_handler = helper.history_handler(); 588 ASSERT_TRUE(history_handler); 589 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 590 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); 591 EXPECT_EQ(page_url, history_handler->page_url_); 592 593 // Simulate not find icon. 594 history_handler->history_results_.clear(); 595 history_handler->InvokeCallback(); 596 597 // Favicon should request to download icon now. 598 DownloadHandler* download_handler = helper.download_handler(); 599 EXPECT_TRUE(helper.download_handler()->HasDownload()); 600 601 // Verify the download request. 602 EXPECT_EQ(new_icon_url, download_handler->GetImageUrl()); 603 604 // Reset the history_handler to verify whether favicon is set. 605 helper.set_history_handler(NULL); 606 607 // Smulates download done. 608 download_handler->InvokeCallback(); 609 610 // New icon should be saved to history backend and navigation entry. 611 history_handler = helper.history_handler(); 612 ASSERT_TRUE(history_handler); 613 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 614 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); 615 EXPECT_LT(0U, history_handler->bitmap_data_.size()); 616 EXPECT_EQ(page_url, history_handler->page_url_); 617 618 // Verify NavigationEntry. 619 content::FaviconStatus favicon_status = helper.GetEntry()->GetFavicon(); 620 EXPECT_EQ(new_icon_url, favicon_status.url); 621 EXPECT_TRUE(favicon_status.valid); 622 EXPECT_FALSE(favicon_status.image.IsEmpty()); 623 EXPECT_EQ(gfx::kFaviconSize, favicon_status.image.Width()); 624 } 625 626 TEST_F(FaviconHandlerTest, FaviconInHistoryInvalid) { 627 const GURL page_url("http://www.google.com"); 628 const GURL icon_url("http://www.google.com/favicon"); 629 630 TestFaviconHandlerDelegate delegate; 631 Profile* profile = Profile::FromBrowserContext( 632 web_contents()->GetBrowserContext()); 633 TestFaviconHandler helper(page_url, profile, 634 &delegate, FaviconHandler::FAVICON); 635 636 helper.FetchFavicon(page_url); 637 HistoryRequestHandler* history_handler = helper.history_handler(); 638 // Ensure the data given to history is correct. 639 ASSERT_TRUE(history_handler); 640 EXPECT_EQ(page_url, history_handler->page_url_); 641 EXPECT_EQ(GURL(), history_handler->icon_url_); 642 EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_); 643 644 // Set non empty but invalid data. 645 chrome::FaviconBitmapResult bitmap_result; 646 bitmap_result.expired = false; 647 // Empty bitmap data is invalid. 648 bitmap_result.bitmap_data = new base::RefCountedBytes(); 649 bitmap_result.pixel_size = gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize); 650 bitmap_result.icon_type = chrome::FAVICON; 651 bitmap_result.icon_url = icon_url; 652 history_handler->history_results_.clear(); 653 history_handler->history_results_.push_back(bitmap_result); 654 655 // Send history response. 656 history_handler->InvokeCallback(); 657 // The NavigationEntry should not be set yet as the history data is invalid. 658 EXPECT_FALSE(helper.GetEntry()->GetFavicon().valid); 659 EXPECT_EQ(GURL(), helper.GetEntry()->GetFavicon().url); 660 661 // Reset the history_handler to verify whether new icon is requested from 662 // history. 663 helper.set_history_handler(NULL); 664 665 // Simulates update with matching favicon URL. 666 std::vector<FaviconURL> urls; 667 urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON)); 668 helper.OnUpdateFaviconURL(0, urls); 669 670 // A download for the favicon should be requested, and we should not do 671 // another history request. 672 DownloadHandler* download_handler = helper.download_handler(); 673 EXPECT_TRUE(helper.download_handler()->HasDownload()); 674 EXPECT_EQ(NULL, helper.history_handler()); 675 676 // Verify the download request. 677 EXPECT_EQ(icon_url, download_handler->GetImageUrl()); 678 679 // Simulates download done. 680 download_handler->InvokeCallback(); 681 682 // New icon should be saved to history backend and navigation entry. 683 history_handler = helper.history_handler(); 684 ASSERT_TRUE(history_handler); 685 EXPECT_EQ(icon_url, history_handler->icon_url_); 686 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); 687 EXPECT_LT(0U, history_handler->bitmap_data_.size()); 688 EXPECT_EQ(page_url, history_handler->page_url_); 689 690 // Verify NavigationEntry. 691 content::FaviconStatus favicon_status = helper.GetEntry()->GetFavicon(); 692 EXPECT_EQ(icon_url, favicon_status.url); 693 EXPECT_TRUE(favicon_status.valid); 694 EXPECT_FALSE(favicon_status.image.IsEmpty()); 695 EXPECT_EQ(gfx::kFaviconSize, favicon_status.image.Width()); 696 } 697 698 TEST_F(FaviconHandlerTest, UpdateFavicon) { 699 const GURL page_url("http://www.google.com"); 700 const GURL icon_url("http://www.google.com/favicon"); 701 const GURL new_icon_url("http://www.google.com/new_favicon"); 702 703 TestFaviconHandlerDelegate delegate; 704 Profile* profile = Profile::FromBrowserContext( 705 web_contents()->GetBrowserContext()); 706 TestFaviconHandler helper(page_url, profile, 707 &delegate, FaviconHandler::FAVICON); 708 709 helper.FetchFavicon(page_url); 710 HistoryRequestHandler* history_handler = helper.history_handler(); 711 // Ensure the data given to history is correct. 712 ASSERT_TRUE(history_handler); 713 EXPECT_EQ(page_url, history_handler->page_url_); 714 EXPECT_EQ(GURL(), history_handler->icon_url_); 715 EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_); 716 717 SetFaviconBitmapResult(icon_url, &history_handler->history_results_); 718 719 // Send history response. 720 history_handler->InvokeCallback(); 721 // Verify FaviconHandler status. 722 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid); 723 EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url); 724 725 // Reset the history_handler to verify whether new icon is requested from 726 // history. 727 helper.set_history_handler(NULL); 728 729 // Simulates update with the different favicon url. 730 std::vector<FaviconURL> urls; 731 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON)); 732 helper.OnUpdateFaviconURL(0, urls); 733 734 // Verify FaviconHandler status. 735 EXPECT_EQ(1U, helper.urls().size()); 736 ASSERT_TRUE(helper.current_candidate()); 737 ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url); 738 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type); 739 740 // Favicon should be requested from history. 741 history_handler = helper.history_handler(); 742 ASSERT_TRUE(history_handler); 743 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 744 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); 745 EXPECT_EQ(page_url, history_handler->page_url_); 746 747 // Simulate find icon. 748 SetFaviconBitmapResult(new_icon_url, &history_handler->history_results_); 749 history_handler->InvokeCallback(); 750 751 // Shouldn't request download favicon 752 EXPECT_FALSE(helper.download_handler()->HasDownload()); 753 754 // Verify the favicon status. 755 EXPECT_EQ(new_icon_url, helper.GetEntry()->GetFavicon().url); 756 EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid); 757 EXPECT_FALSE(helper.GetEntry()->GetFavicon().image.IsEmpty()); 758 } 759 760 TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) { 761 const GURL page_url("http://www.google.com"); 762 const GURL icon_url("http://www.google.com/favicon"); 763 const GURL new_icon_url("http://www.google.com/new_favicon"); 764 765 TestFaviconHandlerDelegate delegate; 766 Profile* profile = Profile::FromBrowserContext( 767 web_contents()->GetBrowserContext()); 768 TestFaviconHandler helper(page_url, profile, 769 &delegate, FaviconHandler::TOUCH); 770 771 helper.FetchFavicon(page_url); 772 HistoryRequestHandler* history_handler = helper.history_handler(); 773 // Ensure the data given to history is correct. 774 ASSERT_TRUE(history_handler); 775 EXPECT_EQ(page_url, history_handler->page_url_); 776 EXPECT_EQ(GURL(), history_handler->icon_url_); 777 EXPECT_EQ(chrome::TOUCH_PRECOMPOSED_ICON | chrome::TOUCH_ICON, 778 history_handler->icon_type_); 779 780 // Icon not found. 781 history_handler->history_results_.clear(); 782 // Send history response. 783 history_handler->InvokeCallback(); 784 // Verify FaviconHandler status. 785 EXPECT_FALSE(helper.GetEntry()->GetFavicon().valid); 786 EXPECT_EQ(GURL(), helper.GetEntry()->GetFavicon().url); 787 788 // Reset the history_handler to verify whether new icon is requested from 789 // history. 790 helper.set_history_handler(NULL); 791 792 // Simulates update with the different favicon url. 793 std::vector<FaviconURL> urls; 794 urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON)); 795 urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON)); 796 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON)); 797 helper.OnUpdateFaviconURL(0, urls); 798 799 // Verify FaviconHandler status. 800 EXPECT_EQ(2U, helper.urls().size()); 801 ASSERT_TRUE(helper.current_candidate()); 802 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); 803 ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, 804 helper.current_candidate()->icon_type); 805 806 // Favicon should be requested from history. 807 history_handler = helper.history_handler(); 808 ASSERT_TRUE(history_handler); 809 EXPECT_EQ(icon_url, history_handler->icon_url_); 810 EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_); 811 EXPECT_EQ(page_url, history_handler->page_url_); 812 813 // Simulate not find icon. 814 history_handler->history_results_.clear(); 815 history_handler->InvokeCallback(); 816 817 // Should request download favicon. 818 DownloadHandler* download_handler = helper.download_handler(); 819 EXPECT_TRUE(helper.download_handler()->HasDownload()); 820 821 // Verify the download request. 822 EXPECT_EQ(icon_url, download_handler->GetImageUrl()); 823 824 // Reset the history_handler to verify whether favicon is request from 825 // history. 826 helper.set_history_handler(NULL); 827 // Smulates download failed. 828 download_handler->set_failed(true); 829 download_handler->InvokeCallback(); 830 831 // Left 1 url. 832 EXPECT_EQ(1U, helper.urls().size()); 833 ASSERT_TRUE(helper.current_candidate()); 834 EXPECT_EQ(new_icon_url, helper.current_candidate()->icon_url); 835 EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type); 836 837 // Favicon should be requested from history. 838 history_handler = helper.history_handler(); 839 ASSERT_TRUE(history_handler); 840 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 841 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_); 842 EXPECT_EQ(page_url, history_handler->page_url_); 843 844 // Reset download handler 845 download_handler->Reset(); 846 847 // Simulates getting a expired icon from history. 848 SetFaviconBitmapResult(new_icon_url, chrome::TOUCH_ICON, 849 true /* expired */, &history_handler->history_results_); 850 history_handler->InvokeCallback(); 851 852 // Verify the download request. 853 EXPECT_TRUE(helper.download_handler()->HasDownload()); 854 EXPECT_EQ(new_icon_url, download_handler->GetImageUrl()); 855 856 helper.set_history_handler(NULL); 857 858 // Simulates icon being downloaded. 859 download_handler->InvokeCallback(); 860 861 // New icon should be saved to history backend. 862 history_handler = helper.history_handler(); 863 ASSERT_TRUE(history_handler); 864 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 865 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_); 866 EXPECT_LT(0U, history_handler->bitmap_data_.size()); 867 EXPECT_EQ(page_url, history_handler->page_url_); 868 } 869 870 TEST_F(FaviconHandlerTest, UpdateDuringDownloading) { 871 const GURL page_url("http://www.google.com"); 872 const GURL icon_url("http://www.google.com/favicon"); 873 const GURL new_icon_url("http://www.google.com/new_favicon"); 874 875 TestFaviconHandlerDelegate delegate; 876 Profile* profile = Profile::FromBrowserContext( 877 web_contents()->GetBrowserContext()); 878 TestFaviconHandler helper(page_url, profile, 879 &delegate, FaviconHandler::TOUCH); 880 881 helper.FetchFavicon(page_url); 882 HistoryRequestHandler* history_handler = helper.history_handler(); 883 // Ensure the data given to history is correct. 884 ASSERT_TRUE(history_handler); 885 EXPECT_EQ(page_url, history_handler->page_url_); 886 EXPECT_EQ(GURL(), history_handler->icon_url_); 887 EXPECT_EQ(chrome::TOUCH_PRECOMPOSED_ICON | chrome::TOUCH_ICON, 888 history_handler->icon_type_); 889 890 // Icon not found. 891 history_handler->history_results_.clear(); 892 // Send history response. 893 history_handler->InvokeCallback(); 894 // Verify FaviconHandler status. 895 EXPECT_FALSE(helper.GetEntry()->GetFavicon().valid); 896 EXPECT_EQ(GURL(), helper.GetEntry()->GetFavicon().url); 897 898 // Reset the history_handler to verify whether new icon is requested from 899 // history. 900 helper.set_history_handler(NULL); 901 902 // Simulates update with the different favicon url. 903 std::vector<FaviconURL> urls; 904 urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON)); 905 urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON)); 906 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON)); 907 helper.OnUpdateFaviconURL(0, urls); 908 909 // Verify FaviconHandler status. 910 EXPECT_EQ(2U, helper.urls().size()); 911 ASSERT_TRUE(helper.current_candidate()); 912 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); 913 ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, 914 helper.current_candidate()->icon_type); 915 916 // Favicon should be requested from history. 917 history_handler = helper.history_handler(); 918 ASSERT_TRUE(history_handler); 919 EXPECT_EQ(icon_url, history_handler->icon_url_); 920 EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_); 921 EXPECT_EQ(page_url, history_handler->page_url_); 922 923 // Simulate not find icon. 924 history_handler->history_results_.clear(); 925 history_handler->InvokeCallback(); 926 927 // Should request download favicon. 928 DownloadHandler* download_handler = helper.download_handler(); 929 EXPECT_TRUE(helper.download_handler()->HasDownload()); 930 931 // Verify the download request. 932 EXPECT_EQ(icon_url, download_handler->GetImageUrl()); 933 934 // Reset the history_handler to verify whether favicon is request from 935 // history. 936 helper.set_history_handler(NULL); 937 const GURL latest_icon_url("http://www.google.com/latest_favicon"); 938 std::vector<FaviconURL> latest_urls; 939 latest_urls.push_back(FaviconURL(latest_icon_url, FaviconURL::TOUCH_ICON)); 940 helper.OnUpdateFaviconURL(0, latest_urls); 941 942 EXPECT_EQ(1U, helper.urls().size()); 943 EXPECT_EQ(latest_icon_url, helper.current_candidate()->icon_url); 944 EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type); 945 946 // Whether new icon is requested from history 947 history_handler = helper.history_handler(); 948 ASSERT_TRUE(history_handler); 949 EXPECT_EQ(latest_icon_url, history_handler->icon_url_); 950 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_); 951 EXPECT_EQ(page_url, history_handler->page_url_); 952 953 // Reset the history_handler to verify whether favicon is request from 954 // history. 955 // Save the callback for late use. 956 FaviconService::FaviconResultsCallback callback = history_handler->callback_; 957 helper.set_history_handler(NULL); 958 959 // Simulates download succeed. 960 download_handler->InvokeCallback(); 961 // The downloaded icon should be thrown away as there is favicon update. 962 EXPECT_FALSE(helper.history_handler()); 963 964 download_handler->Reset(); 965 966 // Simulates getting the icon from history. 967 scoped_ptr<HistoryRequestHandler> handler; 968 handler.reset(new HistoryRequestHandler(page_url, latest_icon_url, 969 chrome::TOUCH_ICON, callback)); 970 SetFaviconBitmapResult(latest_icon_url, chrome::TOUCH_ICON, 971 false /* expired */, &handler->history_results_); 972 handler->InvokeCallback(); 973 974 // No download request. 975 EXPECT_FALSE(download_handler->HasDownload()); 976 } 977 978 #if !defined(OS_ANDROID) 979 980 // Test the favicon which is selected when the web page provides several 981 // favicons and none of the favicons are cached in history. 982 // The goal of this test is to be more of an integration test than 983 // SelectFaviconFramesTest.*. 984 TEST_F(FaviconHandlerTest, MultipleFavicons) { 985 const GURL kPageURL("http://www.google.com"); 986 const FaviconURL kSourceIconURLs[] = { 987 FaviconURL(GURL("http://www.google.com/a"), FaviconURL::FAVICON), 988 FaviconURL(GURL("http://www.google.com/b"), FaviconURL::FAVICON), 989 FaviconURL(GURL("http://www.google.com/c"), FaviconURL::FAVICON), 990 FaviconURL(GURL("http://www.google.com/d"), FaviconURL::FAVICON), 991 FaviconURL(GURL("http://www.google.com/e"), FaviconURL::FAVICON) 992 }; 993 994 // Set the supported scale factors to 1x and 2x. This affects the behavior of 995 // SelectFaviconFrames(). 996 std::vector<ui::ScaleFactor> scale_factors; 997 scale_factors.push_back(ui::SCALE_FACTOR_100P); 998 scale_factors.push_back(ui::SCALE_FACTOR_200P); 999 ui::test::ScopedSetSupportedScaleFactors scoped_supported(scale_factors); 1000 1001 Profile* profile = Profile::FromBrowserContext( 1002 web_contents()->GetBrowserContext()); 1003 1004 // 1) Test that if there are several single resolution favicons to choose from 1005 // that the largest exact match is chosen. 1006 TestFaviconHandlerDelegate delegate1; 1007 TestFaviconHandler handler1(kPageURL, profile, 1008 &delegate1, FaviconHandler::FAVICON); 1009 const int kSizes1[] = { 16, 24, 32, 48, 256 }; 1010 std::vector<FaviconURL> urls1(kSourceIconURLs, 1011 kSourceIconURLs + arraysize(kSizes1)); 1012 DownloadTillDoneIgnoringHistory(&handler1, kPageURL, urls1, kSizes1); 1013 1014 content::FaviconStatus favicon_status1(handler1.GetEntry()->GetFavicon()); 1015 EXPECT_EQ(0u, handler1.image_urls().size()); 1016 EXPECT_TRUE(favicon_status1.valid); 1017 EXPECT_FALSE(favicon_status1.image.IsEmpty()); 1018 EXPECT_EQ(gfx::kFaviconSize, favicon_status1.image.Width()); 1019 1020 size_t expected_index = 2u; 1021 EXPECT_EQ(32, kSizes1[expected_index]); 1022 EXPECT_EQ(kSourceIconURLs[expected_index].icon_url, 1023 handler1.GetEntry()->GetFavicon().url); 1024 1025 // 2) Test that if there are several single resolution favicons to choose 1026 // from, the exact match is preferred even if it results in upsampling. 1027 TestFaviconHandlerDelegate delegate2; 1028 TestFaviconHandler handler2(kPageURL, profile, 1029 &delegate2, FaviconHandler::FAVICON); 1030 const int kSizes2[] = { 16, 24, 48, 256 }; 1031 std::vector<FaviconURL> urls2(kSourceIconURLs, 1032 kSourceIconURLs + arraysize(kSizes2)); 1033 DownloadTillDoneIgnoringHistory(&handler2, kPageURL, urls2, kSizes2); 1034 EXPECT_TRUE(handler2.GetEntry()->GetFavicon().valid); 1035 expected_index = 0u; 1036 EXPECT_EQ(16, kSizes2[expected_index]); 1037 EXPECT_EQ(kSourceIconURLs[expected_index].icon_url, 1038 handler2.GetEntry()->GetFavicon().url); 1039 1040 // 3) Test that favicons which need to be upsampled a little or downsampled 1041 // a little are preferred over huge favicons. 1042 TestFaviconHandlerDelegate delegate3; 1043 TestFaviconHandler handler3(kPageURL, profile, 1044 &delegate3, FaviconHandler::FAVICON); 1045 const int kSizes3[] = { 256, 48 }; 1046 std::vector<FaviconURL> urls3(kSourceIconURLs, 1047 kSourceIconURLs + arraysize(kSizes3)); 1048 DownloadTillDoneIgnoringHistory(&handler3, kPageURL, urls3, kSizes3); 1049 EXPECT_TRUE(handler3.GetEntry()->GetFavicon().valid); 1050 expected_index = 1u; 1051 EXPECT_EQ(48, kSizes3[expected_index]); 1052 EXPECT_EQ(kSourceIconURLs[expected_index].icon_url, 1053 handler3.GetEntry()->GetFavicon().url); 1054 1055 TestFaviconHandlerDelegate delegate4; 1056 TestFaviconHandler handler4(kPageURL, profile, 1057 &delegate4, FaviconHandler::FAVICON); 1058 const int kSizes4[] = { 17, 256 }; 1059 std::vector<FaviconURL> urls4(kSourceIconURLs, 1060 kSourceIconURLs + arraysize(kSizes4)); 1061 DownloadTillDoneIgnoringHistory(&handler4, kPageURL, urls4, kSizes4); 1062 EXPECT_TRUE(handler4.GetEntry()->GetFavicon().valid); 1063 expected_index = 0u; 1064 EXPECT_EQ(17, kSizes4[expected_index]); 1065 EXPECT_EQ(kSourceIconURLs[expected_index].icon_url, 1066 handler4.GetEntry()->GetFavicon().url); 1067 } 1068 1069 #endif 1070 1071 static BrowserContextKeyedService* BuildFaviconService( 1072 content::BrowserContext* profile) { 1073 return new FaviconService(static_cast<Profile*>(profile)); 1074 } 1075 1076 static BrowserContextKeyedService* BuildHistoryService( 1077 content::BrowserContext* profile) { 1078 return NULL; 1079 } 1080 1081 // Test that Favicon is not requested repeatedly during the same session if 1082 // server returns HTTP 404 status. 1083 TEST_F(FaviconHandlerTest, UnableToDownloadFavicon) { 1084 const GURL missing_icon_url("http://www.google.com/favicon.ico"); 1085 const GURL another_icon_url("http://www.youtube.com/favicon.ico"); 1086 1087 Profile* profile = Profile::FromBrowserContext( 1088 web_contents()->GetBrowserContext()); 1089 1090 FaviconServiceFactory::GetInstance()->SetTestingFactory( 1091 profile, BuildFaviconService); 1092 1093 HistoryServiceFactory::GetInstance()->SetTestingFactory( 1094 profile, BuildHistoryService); 1095 1096 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( 1097 profile, Profile::IMPLICIT_ACCESS); 1098 1099 FaviconTabHelper::CreateForWebContents(web_contents()); 1100 FaviconTabHelper* favicon_tab_helper = 1101 FaviconTabHelper::FromWebContents(web_contents()); 1102 1103 std::vector<SkBitmap> empty_icons; 1104 std::vector<gfx::Size> empty_icon_sizes; 1105 int download_id = 0; 1106 1107 // Try to download missing icon. 1108 download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0); 1109 EXPECT_NE(0, download_id); 1110 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url)); 1111 1112 // Report download failure with HTTP 503 status. 1113 favicon_tab_helper->DidDownloadFavicon(download_id, 503, missing_icon_url, 1114 empty_icons, empty_icon_sizes); 1115 // Icon is not marked as UnableToDownload as HTTP status is not 404. 1116 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url)); 1117 1118 // Try to download again. 1119 download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0); 1120 EXPECT_NE(0, download_id); 1121 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url)); 1122 1123 // Report download failure with HTTP 404 status. 1124 favicon_tab_helper->DidDownloadFavicon(download_id, 404, missing_icon_url, 1125 empty_icons, empty_icon_sizes); 1126 // Icon is marked as UnableToDownload. 1127 EXPECT_TRUE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url)); 1128 1129 // Try to download again. 1130 download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0); 1131 // Download is not started and Icon is still marked as UnableToDownload. 1132 EXPECT_EQ(0, download_id); 1133 EXPECT_TRUE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url)); 1134 1135 // Try to download another icon. 1136 download_id = favicon_tab_helper->StartDownload(another_icon_url, 0); 1137 // Download is started as another icon URL is not same as missing_icon_url. 1138 EXPECT_NE(0, download_id); 1139 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(another_icon_url)); 1140 1141 // Clear the list of missing icons. 1142 favicon_service->ClearUnableToDownloadFavicons(); 1143 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url)); 1144 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(another_icon_url)); 1145 1146 // Try to download again. 1147 download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0); 1148 EXPECT_NE(0, download_id); 1149 // Report download success with HTTP 200 status. 1150 favicon_tab_helper->DidDownloadFavicon(download_id, 200, missing_icon_url, 1151 empty_icons, empty_icon_sizes); 1152 // Icon is not marked as UnableToDownload as HTTP status is not 404. 1153 EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url)); 1154 } 1155 1156 } // namespace. 1157