OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/favicon/favicon_handler.h" | 5 #include "chrome/browser/favicon/favicon_handler.h" |
6 | 6 |
7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 std::string UrlWithoutFragment(const GURL& gurl) { | 54 std::string UrlWithoutFragment(const GURL& gurl) { |
55 GURL::Replacements replacements; | 55 GURL::Replacements replacements; |
56 replacements.ClearRef(); | 56 replacements.ClearRef(); |
57 return gurl.ReplaceComponents(replacements).spec(); | 57 return gurl.ReplaceComponents(replacements).spec(); |
58 } | 58 } |
59 | 59 |
60 bool UrlMatches(const GURL& gurl_a, const GURL& gurl_b) { | 60 bool UrlMatches(const GURL& gurl_a, const GURL& gurl_b) { |
61 return UrlWithoutFragment(gurl_a) == UrlWithoutFragment(gurl_b); | 61 return UrlWithoutFragment(gurl_a) == UrlWithoutFragment(gurl_b); |
62 } | 62 } |
63 | 63 |
| 64 // Returns true if at least one of the bitmaps in |favicon_bitmap_results| is |
| 65 // expired. |
| 66 bool HasExpiredFaviconResult( |
| 67 const std::vector<history::FaviconBitmapResult>& favicon_bitmap_results) { |
| 68 for (size_t i = 0; i < favicon_bitmap_results.size(); ++i) { |
| 69 if (favicon_bitmap_results[i].expired) |
| 70 return true; |
| 71 } |
| 72 return false; |
| 73 } |
| 74 |
64 } // namespace | 75 } // namespace |
65 | 76 |
66 //////////////////////////////////////////////////////////////////////////////// | 77 //////////////////////////////////////////////////////////////////////////////// |
67 | 78 |
68 FaviconHandler::DownloadRequest::DownloadRequest() | 79 FaviconHandler::DownloadRequest::DownloadRequest() |
69 : icon_type(history::INVALID_ICON) { | 80 : icon_type(history::INVALID_ICON) { |
70 } | 81 } |
71 | 82 |
72 FaviconHandler::DownloadRequest::~DownloadRequest() { | 83 FaviconHandler::DownloadRequest::~DownloadRequest() { |
73 } | 84 } |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 | 282 |
272 // For FAVICON. | 283 // For FAVICON. |
273 if (current_candidate()->icon_type == FaviconURL::FAVICON) { | 284 if (current_candidate()->icon_type == FaviconURL::FAVICON) { |
274 if (!favicon_expired_ && entry->GetFavicon().valid && | 285 if (!favicon_expired_ && entry->GetFavicon().valid && |
275 DoUrlAndIconMatch(*current_candidate(), entry->GetFavicon().url, | 286 DoUrlAndIconMatch(*current_candidate(), entry->GetFavicon().url, |
276 history::FAVICON)) | 287 history::FAVICON)) |
277 return; | 288 return; |
278 | 289 |
279 entry->GetFavicon().url = current_candidate()->icon_url; | 290 entry->GetFavicon().url = current_candidate()->icon_url; |
280 } else if (!favicon_expired_ && got_favicon_from_history_ && | 291 } else if (!favicon_expired_ && got_favicon_from_history_ && |
281 history_icon_.is_valid() && | 292 !history_results_.empty()) { |
282 DoUrlAndIconMatch( | 293 const history::FaviconBitmapResult& bitmap_result = history_results_[0]; |
283 *current_candidate(), | 294 if (bitmap_result.is_valid() && |
284 history_icon_.icon_url, history_icon_.icon_type)) { | 295 DoUrlAndIconMatch(*current_candidate(), bitmap_result.icon_url, |
285 return; | 296 bitmap_result.icon_type)) { |
| 297 return; |
| 298 } |
286 } | 299 } |
287 | 300 |
288 if (got_favicon_from_history_) | 301 if (got_favicon_from_history_) |
289 DownloadFaviconOrAskHistory(entry->GetURL(), current_candidate()->icon_url, | 302 DownloadFaviconOrAskHistory(entry->GetURL(), current_candidate()->icon_url, |
290 ToHistoryIconType(current_candidate()->icon_type)); | 303 ToHistoryIconType(current_candidate()->icon_type)); |
291 } | 304 } |
292 | 305 |
293 void FaviconHandler::OnDidDownloadFavicon(int id, | 306 void FaviconHandler::OnDidDownloadFavicon(int id, |
294 const GURL& image_url, | 307 const GURL& image_url, |
295 bool errored, | 308 bool errored, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 } | 362 } |
350 int id = delegate_->StartDownload(image_url, image_size); | 363 int id = delegate_->StartDownload(image_url, image_size); |
351 return id; | 364 return id; |
352 } | 365 } |
353 | 366 |
354 void FaviconHandler::UpdateFaviconMappingAndFetch( | 367 void FaviconHandler::UpdateFaviconMappingAndFetch( |
355 const GURL& page_url, | 368 const GURL& page_url, |
356 const GURL& icon_url, | 369 const GURL& icon_url, |
357 history::IconType icon_type, | 370 history::IconType icon_type, |
358 CancelableRequestConsumerBase* consumer, | 371 CancelableRequestConsumerBase* consumer, |
359 const FaviconService::FaviconDataCallback& callback) { | 372 const FaviconService::FaviconResultsCallback& callback) { |
360 GetFaviconService()->UpdateFaviconMappingAndFetch(page_url, icon_url, | 373 GetFaviconService()->UpdateFaviconMappingAndFetch(page_url, icon_url, |
361 icon_type, consumer, callback); | 374 icon_type, consumer, callback); |
362 } | 375 } |
363 | 376 |
364 void FaviconHandler::GetFavicon( | 377 void FaviconHandler::GetFavicon( |
365 const GURL& icon_url, | 378 const GURL& icon_url, |
366 history::IconType icon_type, | 379 history::IconType icon_type, |
367 CancelableRequestConsumerBase* consumer, | 380 CancelableRequestConsumerBase* consumer, |
368 const FaviconService::FaviconDataCallback& callback) { | 381 const FaviconService::FaviconResultsCallback& callback) { |
369 GetFaviconService()->GetFavicon(icon_url, icon_type, consumer, callback); | 382 GetFaviconService()->GetFavicon(icon_url, icon_type, preferred_icon_size(), |
| 383 ui::GetSupportedScaleFactors(), consumer, callback); |
370 } | 384 } |
371 | 385 |
372 void FaviconHandler::GetFaviconForURL( | 386 void FaviconHandler::GetFaviconForURL( |
373 const GURL& page_url, | 387 const GURL& page_url, |
374 int icon_types, | 388 int icon_types, |
375 CancelableRequestConsumerBase* consumer, | 389 CancelableRequestConsumerBase* consumer, |
376 const FaviconService::FaviconDataCallback& callback) { | 390 const FaviconService::FaviconResultsCallback& callback) { |
377 GetFaviconService()->GetFaviconForURL(profile_, page_url, icon_types, | 391 GetFaviconService()->GetFaviconForURL(profile_, page_url, icon_types, |
378 consumer, callback); | 392 preferred_icon_size(), ui::GetSupportedScaleFactors(), consumer, |
| 393 callback); |
379 } | 394 } |
380 | 395 |
381 void FaviconHandler::SetHistoryFavicon( | 396 void FaviconHandler::SetHistoryFavicon( |
382 const GURL& page_url, | 397 const GURL& page_url, |
383 const GURL& icon_url, | 398 const GURL& icon_url, |
384 const std::vector<unsigned char>& image_data, | 399 const std::vector<unsigned char>& image_data, |
385 history::IconType icon_type) { | 400 history::IconType icon_type) { |
386 GetFaviconService()->SetFavicon(page_url, icon_url, image_data, icon_type); | 401 GetFaviconService()->SetFavicon(page_url, icon_url, image_data, icon_type); |
387 } | 402 } |
388 | 403 |
389 bool FaviconHandler::ShouldSaveFavicon(const GURL& url) { | 404 bool FaviconHandler::ShouldSaveFavicon(const GURL& url) { |
390 if (!profile_->IsOffTheRecord()) | 405 if (!profile_->IsOffTheRecord()) |
391 return true; | 406 return true; |
392 | 407 |
393 // Otherwise store the favicon if the page is bookmarked. | 408 // Otherwise store the favicon if the page is bookmarked. |
394 BookmarkModel* bookmark_model = | 409 BookmarkModel* bookmark_model = |
395 BookmarkModelFactory::GetForProfile(profile_); | 410 BookmarkModelFactory::GetForProfile(profile_); |
396 return bookmark_model && bookmark_model->IsBookmarked(url); | 411 return bookmark_model && bookmark_model->IsBookmarked(url); |
397 } | 412 } |
398 | 413 |
399 void FaviconHandler::OnFaviconDataForInitialURL( | 414 void FaviconHandler::OnFaviconDataForInitialURL( |
400 FaviconService::Handle handle, | 415 FaviconService::Handle handle, |
401 history::FaviconData favicon) { | 416 std::vector<history::FaviconBitmapResult> favicon_bitmap_results, |
| 417 history::IconURLSizesMap icon_url_sizes) { |
402 NavigationEntry* entry = GetEntry(); | 418 NavigationEntry* entry = GetEntry(); |
403 if (!entry) | 419 if (!entry) |
404 return; | 420 return; |
405 | 421 |
406 got_favicon_from_history_ = true; | 422 got_favicon_from_history_ = true; |
407 history_icon_ = favicon; | 423 history_results_ = favicon_bitmap_results; |
408 | 424 |
409 favicon_expired_ = (favicon.known_icon && favicon.expired); | 425 bool has_results = !favicon_bitmap_results.empty(); |
| 426 favicon_expired_ = (has_results && |
| 427 HasExpiredFaviconResult(favicon_bitmap_results)); |
410 | 428 |
411 if (favicon.known_icon && favicon.icon_type == history::FAVICON && | 429 history::FaviconBitmapResult bitmap_result; |
| 430 if (has_results) |
| 431 bitmap_result = favicon_bitmap_results[0]; |
| 432 |
| 433 if (has_results && bitmap_result.icon_type == history::FAVICON && |
412 !entry->GetFavicon().valid && | 434 !entry->GetFavicon().valid && |
413 (!current_candidate() || | 435 (!current_candidate() || |
414 DoUrlAndIconMatch( | 436 DoUrlAndIconMatch(*current_candidate(), |
415 *current_candidate(), favicon.icon_url, favicon.icon_type))) { | 437 bitmap_result.icon_url, bitmap_result.icon_type))) { |
416 // The db knows the favicon (although it may be out of date) and the entry | 438 // The db knows the favicon (although it may be out of date) and the entry |
417 // doesn't have an icon. Set the favicon now, and if the favicon turns out | 439 // doesn't have an icon. Set the favicon now, and if the favicon turns out |
418 // to be expired (or the wrong url) we'll fetch later on. This way the | 440 // to be expired (or the wrong url) we'll fetch later on. This way the |
419 // user doesn't see a flash of the default favicon. | 441 // user doesn't see a flash of the default favicon. |
420 entry->GetFavicon().url = favicon.icon_url; | 442 entry->GetFavicon().url = bitmap_result.icon_url; |
421 if (favicon.is_valid()) | 443 if (bitmap_result.is_valid()) |
422 UpdateFavicon(entry, favicon.image_data); | 444 UpdateFavicon(entry, bitmap_result.bitmap_data); |
423 entry->GetFavicon().valid = true; | 445 entry->GetFavicon().valid = true; |
424 } | 446 } |
425 | 447 |
426 if (favicon.known_icon && !favicon.expired) { | 448 if (has_results && !bitmap_result.expired) { |
427 if (current_candidate() && | 449 if (current_candidate() && |
428 !DoUrlAndIconMatch( | 450 !DoUrlAndIconMatch(*current_candidate(), |
429 *current_candidate(), favicon.icon_url, favicon.icon_type)) { | 451 bitmap_result.icon_url, bitmap_result.icon_type)) { |
430 // Mapping in the database is wrong. DownloadFavIconOrAskHistory will | 452 // Mapping in the database is wrong. DownloadFavIconOrAskHistory will |
431 // update the mapping for this url and download the favicon if we don't | 453 // update the mapping for this url and download the favicon if we don't |
432 // already have it. | 454 // already have it. |
433 DownloadFaviconOrAskHistory(entry->GetURL(), | 455 DownloadFaviconOrAskHistory(entry->GetURL(), |
434 current_candidate()->icon_url, | 456 current_candidate()->icon_url, |
435 static_cast<history::IconType>(current_candidate()->icon_type)); | 457 static_cast<history::IconType>(current_candidate()->icon_type)); |
436 } | 458 } |
437 } else if (current_candidate()) { | 459 } else if (current_candidate()) { |
438 // We know the official url for the favicon, by either don't have the | 460 // We know the official url for the favicon, by either don't have the |
439 // favicon or its expired. Continue on to DownloadFaviconOrAskHistory to | 461 // favicon or its expired. Continue on to DownloadFaviconOrAskHistory to |
(...skipping 27 matching lines...) Expand all Loading... |
467 // include the mapping between the page url and the favicon url. | 489 // include the mapping between the page url and the favicon url. |
468 // This is asynchronous. The history service will call back when done. | 490 // This is asynchronous. The history service will call back when done. |
469 // Issue the request and associate the current page ID with it. | 491 // Issue the request and associate the current page ID with it. |
470 UpdateFaviconMappingAndFetch(page_url, icon_url, icon_type, | 492 UpdateFaviconMappingAndFetch(page_url, icon_url, icon_type, |
471 &cancelable_consumer_, | 493 &cancelable_consumer_, |
472 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this))); | 494 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this))); |
473 } | 495 } |
474 } | 496 } |
475 } | 497 } |
476 | 498 |
477 void FaviconHandler::OnFaviconData(FaviconService::Handle handle, | 499 void FaviconHandler::OnFaviconData( |
478 history::FaviconData favicon) { | 500 FaviconService::Handle handle, |
| 501 std::vector<history::FaviconBitmapResult> favicon_bitmap_results, |
| 502 history::IconURLSizesMap icon_url_sizes) { |
479 NavigationEntry* entry = GetEntry(); | 503 NavigationEntry* entry = GetEntry(); |
480 if (!entry) | 504 if (!entry) |
481 return; | 505 return; |
482 | 506 |
| 507 bool has_results = !favicon_bitmap_results.empty(); |
| 508 history::FaviconBitmapResult bitmap_result; |
| 509 if (has_results) |
| 510 bitmap_result = favicon_bitmap_results[0]; |
| 511 |
483 // No need to update the favicon url. By the time we get here | 512 // No need to update the favicon url. By the time we get here |
484 // UpdateFaviconURL will have set the favicon url. | 513 // UpdateFaviconURL will have set the favicon url. |
485 if (favicon.icon_type == history::FAVICON) { | 514 if (has_results && bitmap_result.icon_type == history::FAVICON) { |
486 if (favicon.is_valid()) { | 515 if (bitmap_result.is_valid()) { |
487 // There is a favicon, set it now. If expired we'll download the current | 516 // There is a favicon, set it now. If expired we'll download the current |
488 // one again, but at least the user will get some icon instead of the | 517 // one again, but at least the user will get some icon instead of the |
489 // default and most likely the current one is fine anyway. | 518 // default and most likely the current one is fine anyway. |
490 UpdateFavicon(entry, favicon.image_data); | 519 UpdateFavicon(entry, bitmap_result.bitmap_data); |
491 } | 520 } |
492 if (!favicon.known_icon || favicon.expired) { | 521 if (HasExpiredFaviconResult(favicon_bitmap_results)) { |
493 // We don't know the favicon, or it is out of date. Request the current | 522 // The favicon is out of date. Request the current one. |
494 // one. | |
495 ScheduleDownload(entry->GetURL(), entry->GetFavicon().url, | 523 ScheduleDownload(entry->GetURL(), entry->GetFavicon().url, |
496 preferred_icon_size(), | 524 preferred_icon_size(), |
497 history::FAVICON, | 525 history::FAVICON, |
498 FaviconTabHelper::ImageDownloadCallback()); | 526 FaviconTabHelper::ImageDownloadCallback()); |
499 } | 527 } |
500 } else if (current_candidate() && (!favicon.known_icon || favicon.expired || | 528 } else if (current_candidate() && |
501 !(DoUrlAndIconMatch( | 529 (!has_results || HasExpiredFaviconResult(favicon_bitmap_results) || |
502 *current_candidate(), favicon.icon_url, favicon.icon_type)))) { | 530 !(DoUrlAndIconMatch(*current_candidate(), bitmap_result.icon_url, |
| 531 bitmap_result.icon_type)))) { |
503 // We don't know the favicon, it is out of date or its type is not same as | 532 // We don't know the favicon, it is out of date or its type is not same as |
504 // one got from page. Request the current one. | 533 // one got from page. Request the current one. |
505 ScheduleDownload(entry->GetURL(), current_candidate()->icon_url, | 534 ScheduleDownload(entry->GetURL(), current_candidate()->icon_url, |
506 preferred_icon_size(), | 535 preferred_icon_size(), |
507 ToHistoryIconType(current_candidate()->icon_type), | 536 ToHistoryIconType(current_candidate()->icon_type), |
508 FaviconTabHelper::ImageDownloadCallback()); | 537 FaviconTabHelper::ImageDownloadCallback()); |
509 } | 538 } |
510 history_icon_ = favicon; | 539 history_results_ = favicon_bitmap_results; |
511 } | 540 } |
512 | 541 |
513 int FaviconHandler::ScheduleDownload( | 542 int FaviconHandler::ScheduleDownload( |
514 const GURL& url, | 543 const GURL& url, |
515 const GURL& image_url, | 544 const GURL& image_url, |
516 int image_size, | 545 int image_size, |
517 history::IconType icon_type, | 546 history::IconType icon_type, |
518 const FaviconTabHelper::ImageDownloadCallback& callback) { | 547 const FaviconTabHelper::ImageDownloadCallback& callback) { |
519 const int download_id = DownloadFavicon(image_url, image_size); | 548 const int download_id = DownloadFavicon(image_url, image_size); |
520 if (download_id) { | 549 if (download_id) { |
(...skipping 13 matching lines...) Expand all Loading... |
534 int height = bitmap.height(); | 563 int height = bitmap.height(); |
535 if (width > 0 && height > 0) { | 564 if (width > 0 && height > 0) { |
536 gfx::CalculateFaviconTargetSize(&width, &height); | 565 gfx::CalculateFaviconTargetSize(&width, &height); |
537 return gfx::Image(skia::ImageOperations::Resize( | 566 return gfx::Image(skia::ImageOperations::Resize( |
538 bitmap, skia::ImageOperations::RESIZE_LANCZOS3, | 567 bitmap, skia::ImageOperations::RESIZE_LANCZOS3, |
539 width, height)); | 568 width, height)); |
540 } | 569 } |
541 | 570 |
542 return image; | 571 return image; |
543 } | 572 } |
OLD | NEW |