1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/favicon_helper.h" 6 7#include "content/browser/renderer_host/test_render_view_host.h" 8#include "content/browser/tab_contents/navigation_entry.h" 9#include "content/browser/tab_contents/test_tab_contents.h" 10#include "ui/gfx/codec/png_codec.h" 11#include "ui/gfx/favicon_size.h" 12 13class TestFaviconHelper; 14 15namespace { 16 17// Fill the given bmp with valid png data. 18void FillDataToBitmap(int w, int h, SkBitmap* bmp) { 19 bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h); 20 bmp->allocPixels(); 21 22 unsigned char* src_data = 23 reinterpret_cast<unsigned char*>(bmp->getAddr32(0, 0)); 24 for (int i = 0; i < w * h; i++) { 25 src_data[i * 4 + 0] = static_cast<unsigned char>(i % 255); 26 src_data[i * 4 + 1] = static_cast<unsigned char>(i % 255); 27 src_data[i * 4 + 2] = static_cast<unsigned char>(i % 255); 28 src_data[i * 4 + 3] = static_cast<unsigned char>(i % 255); 29 } 30} 31 32// Fill the given data buffer with valid png data. 33void FillBitmap(int w, int h, std::vector<unsigned char>* output) { 34 SkBitmap bitmap; 35 FillDataToBitmap(w, h, &bitmap); 36 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, output); 37} 38 39// This class is used to save the download request for verifying with test case. 40// It also will be used to invoke the onDidDownload callback. 41class DownloadHandler { 42 public: 43 DownloadHandler(int download_id, 44 const GURL& image_url, 45 int image_size, 46 TestFaviconHelper* favicon_helper) 47 : image_url_(image_url), 48 image_size_(image_size), 49 failed_(false), 50 download_id_(download_id), 51 favicon_helper_(favicon_helper) { 52 FillDataToBitmap(16, 16, &bitmap_); 53 } 54 55 virtual ~DownloadHandler() { 56 } 57 58 static void UpdateFaviconURL(FaviconHelper* helper, 59 const std::vector<FaviconURL> urls); 60 61 void InvokeCallback(); 62 63 void UpdateFaviconURL(const std::vector<FaviconURL> urls); 64 65 const GURL image_url_; 66 const int image_size_; 67 68 // Simulates download failed or not. 69 bool failed_; 70 71 private: 72 // Identified the specific download, will also be passed in 73 // OnDidDownloadFavicon callback. 74 int download_id_; 75 TestFaviconHelper* favicon_helper_; 76 SkBitmap bitmap_; 77 78 DISALLOW_COPY_AND_ASSIGN(DownloadHandler); 79}; 80 81// This class is used to save the history request for verifying with test case. 82// It also will be used to simulate the history response. 83class HistoryRequestHandler { 84 public: 85 HistoryRequestHandler(const GURL& page_url, 86 const GURL& icon_url, 87 int icon_type, 88 FaviconService::FaviconDataCallback* callback) 89 : page_url_(page_url), 90 icon_url_(icon_url), 91 icon_type_(icon_type), 92 callback_(callback) { 93 } 94 95 HistoryRequestHandler(const GURL& page_url, 96 const GURL& icon_url, 97 int icon_type, 98 const std::vector<unsigned char>& image_data, 99 FaviconService::FaviconDataCallback* callback) 100 : page_url_(page_url), 101 icon_url_(icon_url), 102 icon_type_(icon_type), 103 image_data_(image_data), 104 callback_(callback) { 105 } 106 107 virtual ~HistoryRequestHandler() { 108 delete callback_; 109 } 110 void InvokeCallback(); 111 112 const GURL page_url_; 113 const GURL icon_url_; 114 const int icon_type_; 115 const std::vector<unsigned char> image_data_; 116 history::FaviconData favicon_data_; 117 FaviconService::FaviconDataCallback* callback_; 118 119 private: 120 DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler); 121}; 122 123} // namespace 124 125// This class is used to catch the FaviconHelper's download and history request, 126// and also provide the methods to access the FaviconHelper internal. 127class TestFaviconHelper : public FaviconHelper { 128 public: 129 TestFaviconHelper(const GURL& page_url, 130 TabContents* tab_contents, 131 Type type) 132 : FaviconHelper(tab_contents, type), 133 download_image_size_(0), 134 download_id_(0), 135 tab_contents_(tab_contents){ 136 entry_.set_url(page_url); 137 } 138 139 virtual ~TestFaviconHelper() { 140 } 141 142 HistoryRequestHandler* history_handler() { 143 return history_handler_.get(); 144 } 145 146 // This method will take the ownership of the given handler. 147 void set_history_handler(HistoryRequestHandler* handler) { 148 history_handler_.reset(handler); 149 } 150 151 DownloadHandler* download_handler() { 152 return download_handler_.get(); 153 } 154 155 // This method will take the ownership of the given download_handler. 156 void set_download_handler(DownloadHandler* download_handler) { 157 download_handler_.reset(download_handler); 158 } 159 160 virtual NavigationEntry* GetEntry() { 161 return &entry_; 162 } 163 164 const std::vector<FaviconURL>& urls() { 165 return urls_; 166 } 167 168 void FetchFavicon(const GURL& url) { 169 FaviconHelper::FetchFavicon(url); 170 } 171 172 // The methods to access favicon internal. 173 FaviconURL* current_candidate() { 174 return FaviconHelper::current_candidate(); 175 } 176 177 void OnDidDownloadFavicon(int id, 178 const GURL& image_url, 179 bool errored, 180 const SkBitmap& image) { 181 FaviconHelper::OnDidDownloadFavicon(id, image_url, errored, image); 182 } 183 184 protected: 185 virtual void UpdateFaviconMappingAndFetch( 186 const GURL& page_url, 187 const GURL& icon_url, 188 history::IconType icon_type, 189 CancelableRequestConsumerBase* consumer, 190 FaviconService::FaviconDataCallback* callback) OVERRIDE { 191 history_handler_.reset(new HistoryRequestHandler(page_url, icon_url, 192 icon_type, callback)); 193 } 194 195 virtual void GetFavicon( 196 const GURL& icon_url, 197 history::IconType icon_type, 198 CancelableRequestConsumerBase* consumer, 199 FaviconService::FaviconDataCallback* callback) OVERRIDE { 200 history_handler_.reset(new HistoryRequestHandler(GURL(), icon_url, 201 icon_type, callback)); 202 } 203 204 virtual void GetFaviconForURL( 205 const GURL& page_url, 206 int icon_types, 207 CancelableRequestConsumerBase* consumer, 208 FaviconService::FaviconDataCallback* callback) OVERRIDE { 209 history_handler_.reset(new HistoryRequestHandler(page_url, GURL(), 210 icon_types, callback)); 211 } 212 213 virtual int DownloadFavicon(const GURL& image_url, int image_size) OVERRIDE { 214 download_id_++; 215 download_handler_.reset(new DownloadHandler(download_id_, image_url, 216 image_size, this)); 217 return download_id_; 218 } 219 220 virtual void SetHistoryFavicon(const GURL& page_url, 221 const GURL& icon_url, 222 const std::vector<unsigned char>& image_data, 223 history::IconType icon_type) OVERRIDE { 224 history_handler_.reset(new HistoryRequestHandler(page_url, icon_url, 225 icon_type, image_data, NULL)); 226 } 227 228 virtual FaviconService* GetFaviconService() OVERRIDE { 229 // Just give none NULL value, so overridden methods can be hit. 230 return (FaviconService*)(1); 231 } 232 233 virtual bool ShouldSaveFavicon(const GURL& url) OVERRIDE { 234 return true; 235 } 236 237 GURL page_url_; 238 239 GURL download_image_url_; 240 int download_image_size_; 241 242 private: 243 NavigationEntry entry_; 244 245 // The unique id of a download request. It will be returned to a 246 // FaviconHelper. 247 int download_id_; 248 249 TabContents* tab_contents_; 250 scoped_ptr<DownloadHandler> download_handler_; 251 scoped_ptr<HistoryRequestHandler> history_handler_; 252 253 DISALLOW_COPY_AND_ASSIGN(TestFaviconHelper); 254}; 255 256namespace { 257 258void DownloadHandler::UpdateFaviconURL(FaviconHelper* helper, 259 const std::vector<FaviconURL> urls) { 260 helper->OnUpdateFaviconURL(0, urls); 261} 262 263void DownloadHandler::UpdateFaviconURL(const std::vector<FaviconURL> urls) { 264 UpdateFaviconURL(favicon_helper_, urls); 265} 266 267void DownloadHandler::InvokeCallback() { 268 favicon_helper_->OnDidDownloadFavicon(download_id_, image_url_, failed_, 269 bitmap_); 270} 271 272void HistoryRequestHandler::InvokeCallback() { 273 callback_->Run(0, favicon_data_); 274} 275 276class FaviconHelperTest : public RenderViewHostTestHarness { 277}; 278 279TEST_F(FaviconHelperTest, GetFaviconFromHistory) { 280 const GURL page_url("http://www.google.com"); 281 const GURL icon_url("http://www.google.com/favicon"); 282 283 TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON); 284 285 helper.FetchFavicon(page_url); 286 HistoryRequestHandler* history_handler = helper.history_handler(); 287 // Ensure the data given to history is correct. 288 ASSERT_TRUE(history_handler); 289 EXPECT_EQ(page_url, history_handler->page_url_); 290 EXPECT_EQ(GURL(), history_handler->icon_url_); 291 EXPECT_EQ(history::FAVICON, history_handler->icon_type_); 292 293 // Set valid icon data. 294 history_handler->favicon_data_.known_icon = true; 295 history_handler->favicon_data_.icon_type = history::FAVICON; 296 history_handler->favicon_data_.expired = false; 297 history_handler->favicon_data_.icon_url = icon_url; 298 scoped_refptr<RefCountedBytes> data = new RefCountedBytes(); 299 FillBitmap(kFaviconSize, kFaviconSize, &data->data); 300 history_handler->favicon_data_.image_data = data; 301 302 // Send history response. 303 history_handler->InvokeCallback(); 304 // Verify FaviconHelper status 305 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid()); 306 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url()); 307 308 // Simulates update favicon url. 309 std::vector<FaviconURL> urls; 310 urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON)); 311 DownloadHandler::UpdateFaviconURL(&helper, urls); 312 313 // Verify FaviconHelper status 314 EXPECT_EQ(1U, helper.urls().size()); 315 ASSERT_TRUE(helper.current_candidate()); 316 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); 317 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type); 318 319 // Favicon shouldn't request to download icon. 320 DownloadHandler* download_handler = helper.download_handler(); 321 ASSERT_FALSE(download_handler); 322} 323 324TEST_F(FaviconHelperTest, DownloadFavicon) { 325 const GURL page_url("http://www.google.com"); 326 const GURL icon_url("http://www.google.com/favicon"); 327 328 TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON); 329 330 helper.FetchFavicon(page_url); 331 HistoryRequestHandler* history_handler = helper.history_handler(); 332 // Ensure the data given to history is correct. 333 ASSERT_TRUE(history_handler); 334 EXPECT_EQ(page_url, history_handler->page_url_); 335 EXPECT_EQ(GURL(), history_handler->icon_url_); 336 EXPECT_EQ(history::FAVICON, history_handler->icon_type_); 337 338 // Set icon data expired 339 history_handler->favicon_data_.known_icon = true; 340 history_handler->favicon_data_.icon_type = history::FAVICON; 341 history_handler->favicon_data_.expired = true; 342 history_handler->favicon_data_.icon_url = icon_url; 343 // Send history response. 344 history_handler->InvokeCallback(); 345 // Verify FaviconHelper status 346 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid()); 347 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url()); 348 349 // Simulates update favicon url. 350 std::vector<FaviconURL> urls; 351 urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON)); 352 DownloadHandler::UpdateFaviconURL(&helper, urls); 353 354 // Verify FaviconHelper status 355 EXPECT_EQ(1U, helper.urls().size()); 356 ASSERT_TRUE(helper.current_candidate()); 357 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); 358 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type); 359 360 // Favicon should request to download icon now. 361 DownloadHandler* download_handler = helper.download_handler(); 362 ASSERT_TRUE(download_handler); 363 // Verify the download request. 364 EXPECT_EQ(icon_url, download_handler->image_url_); 365 EXPECT_EQ(kFaviconSize, download_handler->image_size_); 366 367 // Reset the history_handler to verify whether favicon is set. 368 helper.set_history_handler(NULL); 369 370 // Smulates download done. 371 download_handler->InvokeCallback(); 372 373 // New icon should be saved to history backend and navigation entry. 374 history_handler = helper.history_handler(); 375 ASSERT_TRUE(history_handler); 376 EXPECT_EQ(icon_url, history_handler->icon_url_); 377 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); 378 EXPECT_LT(0U, history_handler->image_data_.size()); 379 EXPECT_EQ(page_url, history_handler->page_url_); 380 381 // Verify NavigationEntry. 382 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url()); 383 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid()); 384 EXPECT_FALSE(helper.GetEntry()->favicon().bitmap().empty()); 385} 386 387TEST_F(FaviconHelperTest, UpdateAndDownloadFavicon) { 388 const GURL page_url("http://www.google.com"); 389 const GURL icon_url("http://www.google.com/favicon"); 390 const GURL new_icon_url("http://www.google.com/new_favicon"); 391 392 TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON); 393 394 helper.FetchFavicon(page_url); 395 HistoryRequestHandler* history_handler = helper.history_handler(); 396 // Ensure the data given to history is correct. 397 ASSERT_TRUE(history_handler); 398 EXPECT_EQ(page_url, history_handler->page_url_); 399 EXPECT_EQ(GURL(), history_handler->icon_url_); 400 EXPECT_EQ(history::FAVICON, history_handler->icon_type_); 401 402 // Set valid icon data. 403 history_handler->favicon_data_.known_icon = true; 404 history_handler->favicon_data_.icon_type = history::FAVICON; 405 history_handler->favicon_data_.expired = false; 406 history_handler->favicon_data_.icon_url = icon_url; 407 scoped_refptr<RefCountedBytes> data = new RefCountedBytes(); 408 FillBitmap(kFaviconSize, kFaviconSize, &data->data); 409 history_handler->favicon_data_.image_data = data; 410 411 // Send history response. 412 history_handler->InvokeCallback(); 413 // Verify FaviconHelper status. 414 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid()); 415 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url()); 416 417 // Reset the history_handler to verify whether new icon is requested from 418 // history. 419 helper.set_history_handler(NULL); 420 421 // Simulates update with the different favicon url. 422 std::vector<FaviconURL> urls; 423 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON)); 424 DownloadHandler::UpdateFaviconURL(&helper, urls); 425 426 // Verify FaviconHelper status. 427 EXPECT_EQ(1U, helper.urls().size()); 428 ASSERT_TRUE(helper.current_candidate()); 429 ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url); 430 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type); 431 // The favicon status's url should be updated. 432 ASSERT_EQ(new_icon_url, helper.GetEntry()->favicon().url()); 433 434 // Favicon should be requested from history. 435 history_handler = helper.history_handler(); 436 ASSERT_TRUE(history_handler); 437 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 438 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); 439 EXPECT_EQ(page_url, history_handler->page_url_); 440 441 // Simulate not find icon. 442 history_handler->favicon_data_.known_icon = false; 443 history_handler->InvokeCallback(); 444 445 // Favicon should request to download icon now. 446 DownloadHandler* download_handler = helper.download_handler(); 447 ASSERT_TRUE(download_handler); 448 // Verify the download request. 449 EXPECT_EQ(new_icon_url, download_handler->image_url_); 450 EXPECT_EQ(kFaviconSize, download_handler->image_size_); 451 452 // Reset the history_handler to verify whether favicon is set. 453 helper.set_history_handler(NULL); 454 455 // Smulates download done. 456 download_handler->InvokeCallback(); 457 458 // New icon should be saved to history backend and navigation entry. 459 history_handler = helper.history_handler(); 460 ASSERT_TRUE(history_handler); 461 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 462 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); 463 EXPECT_LT(0U, history_handler->image_data_.size()); 464 EXPECT_EQ(page_url, history_handler->page_url_); 465 466 // Verify NavigationEntry. 467 EXPECT_EQ(new_icon_url, helper.GetEntry()->favicon().url()); 468 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid()); 469 EXPECT_FALSE(helper.GetEntry()->favicon().bitmap().empty()); 470} 471 472TEST_F(FaviconHelperTest, UpdateFavicon) { 473 const GURL page_url("http://www.google.com"); 474 const GURL icon_url("http://www.google.com/favicon"); 475 const GURL new_icon_url("http://www.google.com/new_favicon"); 476 477 TestFaviconHelper helper(page_url, contents(), FaviconHelper::FAVICON); 478 479 helper.FetchFavicon(page_url); 480 HistoryRequestHandler* history_handler = helper.history_handler(); 481 // Ensure the data given to history is correct. 482 ASSERT_TRUE(history_handler); 483 EXPECT_EQ(page_url, history_handler->page_url_); 484 EXPECT_EQ(GURL(), history_handler->icon_url_); 485 EXPECT_EQ(history::FAVICON, history_handler->icon_type_); 486 487 // Set valid icon data. 488 history_handler->favicon_data_.known_icon = true; 489 history_handler->favicon_data_.icon_type = history::FAVICON; 490 history_handler->favicon_data_.expired = false; 491 history_handler->favicon_data_.icon_url = icon_url; 492 scoped_refptr<RefCountedBytes> data = new RefCountedBytes(); 493 FillBitmap(kFaviconSize, kFaviconSize, &data->data); 494 history_handler->favicon_data_.image_data = data; 495 496 // Send history response. 497 history_handler->InvokeCallback(); 498 // Verify FaviconHelper status. 499 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid()); 500 EXPECT_EQ(icon_url, helper.GetEntry()->favicon().url()); 501 502 // Reset the history_handler to verify whether new icon is requested from 503 // history. 504 helper.set_history_handler(NULL); 505 506 // Simulates update with the different favicon url. 507 std::vector<FaviconURL> urls; 508 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON)); 509 DownloadHandler::UpdateFaviconURL(&helper, urls); 510 511 // Verify FaviconHelper status. 512 EXPECT_EQ(1U, helper.urls().size()); 513 ASSERT_TRUE(helper.current_candidate()); 514 ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url); 515 ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type); 516 // The favicon status's url should be updated. 517 ASSERT_EQ(new_icon_url, helper.GetEntry()->favicon().url()); 518 519 // Favicon should be requested from history. 520 history_handler = helper.history_handler(); 521 ASSERT_TRUE(history_handler); 522 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 523 EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); 524 EXPECT_EQ(page_url, history_handler->page_url_); 525 526 // Simulate find icon. 527 history_handler->favicon_data_.known_icon = true; 528 history_handler->favicon_data_.icon_type = history::FAVICON; 529 history_handler->favicon_data_.expired = false; 530 history_handler->favicon_data_.icon_url = new_icon_url; 531 history_handler->favicon_data_.image_data = data; 532 history_handler->InvokeCallback(); 533 534 // Shouldn't request download favicon 535 EXPECT_FALSE(helper.download_handler()); 536 537 // Verify the favicon status. 538 EXPECT_EQ(new_icon_url, helper.GetEntry()->favicon().url()); 539 EXPECT_TRUE(helper.GetEntry()->favicon().is_valid()); 540 EXPECT_FALSE(helper.GetEntry()->favicon().bitmap().empty()); 541} 542 543TEST_F(FaviconHelperTest, Download2ndFaviconURLCandidate) { 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 TestFaviconHelper helper(page_url, contents(), FaviconHelper::TOUCH); 549 550 helper.FetchFavicon(page_url); 551 HistoryRequestHandler* history_handler = helper.history_handler(); 552 // Ensure the data given to history is correct. 553 ASSERT_TRUE(history_handler); 554 EXPECT_EQ(page_url, history_handler->page_url_); 555 EXPECT_EQ(GURL(), history_handler->icon_url_); 556 EXPECT_EQ(history::TOUCH_PRECOMPOSED_ICON | history::TOUCH_ICON, 557 history_handler->icon_type_); 558 559 // Icon not found. 560 history_handler->favicon_data_.known_icon = false; 561 // Send history response. 562 history_handler->InvokeCallback(); 563 // Verify FaviconHelper status. 564 EXPECT_FALSE(helper.GetEntry()->favicon().is_valid()); 565 EXPECT_EQ(GURL(), helper.GetEntry()->favicon().url()); 566 567 // Reset the history_handler to verify whether new icon is requested from 568 // history. 569 helper.set_history_handler(NULL); 570 571 // Simulates update with the different favicon url. 572 std::vector<FaviconURL> urls; 573 urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON)); 574 urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON)); 575 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON)); 576 577 DownloadHandler::UpdateFaviconURL(&helper, urls); 578 579 // Verify FaviconHelper status. 580 EXPECT_EQ(2U, helper.urls().size()); 581 ASSERT_TRUE(helper.current_candidate()); 582 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); 583 ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, 584 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(icon_url, history_handler->icon_url_); 590 EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_); 591 EXPECT_EQ(page_url, history_handler->page_url_); 592 593 // Simulate not find icon. 594 history_handler->favicon_data_.known_icon = false; 595 history_handler->InvokeCallback(); 596 597 // Should request download favicon. 598 DownloadHandler* download_handler = helper.download_handler(); 599 EXPECT_TRUE(download_handler); 600 // Verify the download request. 601 EXPECT_EQ(icon_url, download_handler->image_url_); 602 EXPECT_EQ(0, download_handler->image_size_); 603 604 // Reset the history_handler to verify whether favicon is request from 605 // history. 606 helper.set_history_handler(NULL); 607 // Smulates download failed. 608 download_handler->failed_ = true; 609 download_handler->InvokeCallback(); 610 611 // Left 1 url. 612 EXPECT_EQ(1U, helper.urls().size()); 613 ASSERT_TRUE(helper.current_candidate()); 614 EXPECT_EQ(new_icon_url, helper.current_candidate()->icon_url); 615 EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type); 616 617 // Favicon should be requested from history. 618 history_handler = helper.history_handler(); 619 ASSERT_TRUE(history_handler); 620 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 621 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_); 622 EXPECT_EQ(page_url, history_handler->page_url_); 623 624 // Reset download handler 625 helper.set_download_handler(NULL); 626 627 // Smulates getting a expired icon from history. 628 history_handler->favicon_data_.known_icon = true; 629 history_handler->favicon_data_.icon_type = history::TOUCH_ICON; 630 history_handler->favicon_data_.expired = true; 631 history_handler->favicon_data_.icon_url = new_icon_url; 632 scoped_refptr<RefCountedBytes> data = new RefCountedBytes(); 633 FillBitmap(kFaviconSize, kFaviconSize, &data->data); 634 history_handler->favicon_data_.image_data = data; 635 history_handler->InvokeCallback(); 636 637 // Verify the download request. 638 download_handler = helper.download_handler(); 639 EXPECT_TRUE(download_handler); 640 EXPECT_EQ(new_icon_url, download_handler->image_url_); 641 EXPECT_EQ(0, download_handler->image_size_); 642 643 helper.set_history_handler(NULL); 644 645 // Simulates icon being downloaded. 646 download_handler->InvokeCallback(); 647 648 // New icon should be saved to history backend. 649 history_handler = helper.history_handler(); 650 ASSERT_TRUE(history_handler); 651 EXPECT_EQ(new_icon_url, history_handler->icon_url_); 652 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_); 653 EXPECT_LT(0U, history_handler->image_data_.size()); 654 EXPECT_EQ(page_url, history_handler->page_url_); 655} 656 657TEST_F(FaviconHelperTest, UpdateDuringDownloading) { 658 const GURL page_url("http://www.google.com"); 659 const GURL icon_url("http://www.google.com/favicon"); 660 const GURL new_icon_url("http://www.google.com/new_favicon"); 661 662 TestFaviconHelper helper(page_url, contents(), FaviconHelper::TOUCH); 663 664 helper.FetchFavicon(page_url); 665 HistoryRequestHandler* history_handler = helper.history_handler(); 666 // Ensure the data given to history is correct. 667 ASSERT_TRUE(history_handler); 668 EXPECT_EQ(page_url, history_handler->page_url_); 669 EXPECT_EQ(GURL(), history_handler->icon_url_); 670 EXPECT_EQ(history::TOUCH_PRECOMPOSED_ICON | history::TOUCH_ICON, 671 history_handler->icon_type_); 672 673 // Icon not found. 674 history_handler->favicon_data_.known_icon = false; 675 // Send history response. 676 history_handler->InvokeCallback(); 677 // Verify FaviconHelper status. 678 EXPECT_FALSE(helper.GetEntry()->favicon().is_valid()); 679 EXPECT_EQ(GURL(), helper.GetEntry()->favicon().url()); 680 681 // Reset the history_handler to verify whether new icon is requested from 682 // history. 683 helper.set_history_handler(NULL); 684 685 // Simulates update with the different favicon url. 686 std::vector<FaviconURL> urls; 687 urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON)); 688 urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON)); 689 urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON)); 690 691 DownloadHandler::UpdateFaviconURL(&helper, urls); 692 693 // Verify FaviconHelper status. 694 EXPECT_EQ(2U, helper.urls().size()); 695 ASSERT_TRUE(helper.current_candidate()); 696 ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); 697 ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, 698 helper.current_candidate()->icon_type); 699 700 // Favicon should be requested from history. 701 history_handler = helper.history_handler(); 702 ASSERT_TRUE(history_handler); 703 EXPECT_EQ(icon_url, history_handler->icon_url_); 704 EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_); 705 EXPECT_EQ(page_url, history_handler->page_url_); 706 707 // Simulate not find icon. 708 history_handler->favicon_data_.known_icon = false; 709 history_handler->InvokeCallback(); 710 711 // Should request download favicon. 712 DownloadHandler* download_handler = helper.download_handler(); 713 EXPECT_TRUE(download_handler); 714 // Verify the download request. 715 EXPECT_EQ(icon_url, download_handler->image_url_); 716 EXPECT_EQ(0, download_handler->image_size_); 717 718 // Reset the history_handler to verify whether favicon is request from 719 // history. 720 helper.set_history_handler(NULL); 721 const GURL latest_icon_url("http://www.google.com/latest_favicon"); 722 std::vector<FaviconURL> latest_urls; 723 latest_urls.push_back(FaviconURL(latest_icon_url, FaviconURL::TOUCH_ICON)); 724 DownloadHandler::UpdateFaviconURL(&helper, latest_urls); 725 EXPECT_EQ(1U, helper.urls().size()); 726 EXPECT_EQ(latest_icon_url, helper.current_candidate()->icon_url); 727 EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type); 728 729 // Whether new icon is requested from history 730 history_handler = helper.history_handler(); 731 ASSERT_TRUE(history_handler); 732 EXPECT_EQ(latest_icon_url, history_handler->icon_url_); 733 EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_); 734 EXPECT_EQ(page_url, history_handler->page_url_); 735 736 // Reset the history_handler to verify whether favicon is request from 737 // history. 738 // Save the callback for late use. 739 FaviconService::FaviconDataCallback* callback = history_handler->callback_; 740 // Prevent the callback from being released. 741 history_handler->callback_ = NULL; 742 helper.set_history_handler(NULL); 743 744 // Smulates download succeed. 745 download_handler->InvokeCallback(); 746 // The downloaded icon should be thrown away as there is faviocn update. 747 EXPECT_FALSE(helper.history_handler()); 748 749 helper.set_download_handler(NULL); 750 751 // Smulates getting the icon from history. 752 scoped_ptr<HistoryRequestHandler> handler; 753 handler.reset(new HistoryRequestHandler(page_url, latest_icon_url, 754 history::TOUCH_ICON, callback)); 755 handler->favicon_data_.known_icon = true; 756 handler->favicon_data_.expired = false; 757 handler->favicon_data_.icon_type = history::TOUCH_ICON; 758 handler->favicon_data_.icon_url = latest_icon_url; 759 scoped_refptr<RefCountedBytes> data = new RefCountedBytes(); 760 FillBitmap(kFaviconSize, kFaviconSize, &data->data); 761 handler->favicon_data_.image_data = data; 762 763 handler->InvokeCallback(); 764 765 // No download request. 766 EXPECT_FALSE(helper.download_handler()); 767} 768 769} // namespace. 770