15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_handler.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include <cmath> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted_memory.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "build/build_config.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/favicon/core/browser/favicon_client.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/favicon/core/favicon_driver.h" 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/favicon_base/favicon_util.h" 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/favicon_base/select_favicon_frames.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/image_operations.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_util.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using favicon::FaviconURL; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Size (along each axis) of a touch icon. This currently corresponds to 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the apple touch icon for iPad. 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kTouchIconSize = 144; 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Get the maximal icon size in pixels for a icon of type |icon_type| for the 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// current platform. 350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint GetMaximalIconSize(favicon_base::IconType icon_type) { 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (icon_type) { 370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case favicon_base::FAVICON: 381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#if defined(OS_ANDROID) 391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 192; 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#else 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return gfx::ImageSkia::GetMaxSupportedScale() * gfx::kFaviconSize; 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif 430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case favicon_base::TOUCH_ICON: 440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case favicon_base::TOUCH_PRECOMPOSED_ICON: 451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return kTouchIconSize; 460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case favicon_base::INVALID_ICON: 471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 0; 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NOTREACHED(); 501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 0; 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DoUrlAndIconMatch(const FaviconURL& favicon_url, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return favicon_url.icon_url == url && favicon_url.icon_type == icon_type; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if all of the icon URLs and icon types in |bitmap_results| are 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// identical and if they match the icon URL and icon type in |favicon_url|. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns false if |bitmap_results| is empty. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DoUrlsAndIconsMatch( 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FaviconURL& favicon_url, 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapResult>& bitmap_results) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap_results.empty()) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const favicon_base::IconType icon_type = favicon_url.icon_type; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bitmap_results.size(); ++i) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_url.icon_url != bitmap_results[i].icon_url || 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_type != bitmap_results[i].icon_type) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string UrlWithoutFragment(const GURL& gurl) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL::Replacements replacements; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) replacements.ClearRef(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gurl.ReplaceComponents(replacements).spec(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UrlMatches(const GURL& gurl_a, const GURL& gurl_b) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UrlWithoutFragment(gurl_a) == UrlWithoutFragment(gurl_b); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return true if |bitmap_result| is expired. 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool IsExpired(const favicon_base::FaviconRawBitmapResult& bitmap_result) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bitmap_result.expired; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return true if |bitmap_result| is valid. 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool IsValid(const favicon_base::FaviconRawBitmapResult& bitmap_result) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bitmap_result.is_valid(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if at least one of the bitmaps in |bitmap_results| is expired or 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// if |bitmap_results| is missing favicons for |desired_size_in_dip| and one of 1016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// the scale factors in favicon_base::GetFaviconScales(). 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasExpiredOrIncompleteResult( 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int desired_size_in_dip, 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapResult>& bitmap_results) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if at least one of the bitmaps is expired. 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>::const_iterator it = 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find_if(bitmap_results.begin(), bitmap_results.end(), IsExpired); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != bitmap_results.end()) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Any favicon size is good if the desired size is 0. 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (desired_size_in_dip == 0) 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if the favicon for at least one of the scale factors is missing. 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |bitmap_results| should always be complete for data inserted by 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // FaviconHandler as the FaviconHandler stores favicons resized to all 1186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // of favicon_base::GetFaviconScales() into the history backend. 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Examples of when |bitmap_results| can be incomplete: 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - Favicons inserted into the history backend by sync. 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - Favicons for imported bookmarks. 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size> favicon_sizes; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bitmap_results.size(); ++i) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmap_results[i].pixel_size); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::vector<float> favicon_scales = favicon_base::GetFaviconScales(); 1276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (size_t i = 0; i < favicon_scales.size(); ++i) { 1286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int edge_size_in_pixel = std::ceil(desired_size_in_dip * favicon_scales[i]); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(), 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.end(), gfx::Size(edge_size_in_pixel, edge_size_in_pixel)); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it == favicon_sizes.end()) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if at least one of |bitmap_results| is valid. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasValidResult( 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapResult>& bitmap_results) { 140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return std::find_if(bitmap_results.begin(), bitmap_results.end(), IsValid) != 141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bitmap_results.end(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Returns the index of the entry with the largest area that is not larger than 1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// |max_area|; -1 if there is no such match. 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint GetLargestSizeIndex(const std::vector<gfx::Size>& sizes, int max_area) { 1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!sizes.empty()); 1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int ret = -1; 1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (size_t i = 0; i < sizes.size(); ++i) { 1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int area = sizes[i].GetArea(); 1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if ((ret == -1 || sizes[ret].GetArea() < area) && area <= max_area) 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ret = i; 1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return ret; 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Return the index of a size which is same as the given |size|, -1 returned if 1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// there is no such bitmap. 1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint GetIndexBySize(const std::vector<gfx::Size>& sizes, 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const gfx::Size& size) { 1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!sizes.empty()); 1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<gfx::Size>::const_iterator i = 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::find(sizes.begin(), sizes.end(), size); 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (i == sizes.end()) 1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return -1; 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return static_cast<int>(i - sizes.begin()); 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Compare function used for std::stable_sort to sort as descend. 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool CompareIconSize(const FaviconURL& b1, const FaviconURL& b2) { 1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int area1 = 0; 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!b1.icon_sizes.empty()) 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch area1 = b1.icon_sizes.front().GetArea(); 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int area2 = 0; 1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!b2.icon_sizes.empty()) 1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch area2 = b2.icon_sizes.front().GetArea(); 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return area1 > area2; 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::DownloadRequest::DownloadRequest() 1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : icon_type(favicon_base::INVALID_ICON) {} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::DownloadRequest::~DownloadRequest() { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::DownloadRequest::DownloadRequest( 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : url(url), image_url(image_url), icon_type(icon_type) {} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::FaviconCandidate::FaviconCandidate() 2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : score(0), icon_type(favicon_base::INVALID_ICON) {} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::FaviconCandidate::~FaviconCandidate() { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::FaviconCandidate::FaviconCandidate( 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& image, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score, 2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : url(url), 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_url(image_url), 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image(image), 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score(score), 2170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_type(icon_type) {} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2210529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochFaviconHandler::FaviconHandler(FaviconClient* client, 2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FaviconDriver* driver, 2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Type icon_type, 2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool download_largest_icon) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : got_favicon_from_history_(false), 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_expired_or_incomplete_(false), 227a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch icon_types_(icon_type == FAVICON 2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ? favicon_base::FAVICON 2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : favicon_base::TOUCH_ICON | 2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::TOUCH_PRECOMPOSED_ICON), 2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch download_largest_icon_(download_largest_icon), 232a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_(client), 2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu driver_(driver) { 2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(driver_); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::~FaviconHandler() { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::FetchFavicon(const GURL& url) { 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cancelable_task_tracker_.TryCancelAll(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_ = url; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_expired_or_incomplete_ = got_favicon_from_history_ = false; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.clear(); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Request the favicon from the history service. In parallel to this the 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // renderer is going to notify us (well WebContents) when the favicon url is 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // available. 251a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (client_->GetFaviconService()) { 252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetFaviconForURLFromFaviconService( 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_, 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_types_, 255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind( 256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, 257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Unretained(this)), 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FaviconHandler::UpdateFaviconCandidate(const GURL& url, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& image, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score, 2660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool replace_best_favicon_candidate = false; 2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool exact_match = false; 2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (download_largest_icon_) { 2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replace_best_favicon_candidate = 2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image.Size().GetArea() > 2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch best_favicon_candidate_.image.Size().GetArea(); 2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::Size largest = best_favicon_candidate_.image.Size(); 2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (replace_best_favicon_candidate) 2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch largest = image.Size(); 2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // exact match (stop downloading next icon) only if 2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // - current candidate is only candidate. 2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // - next candidate doesn't have sizes attributes, in this case, the rest 2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // candidates don't have sizes attribute either, stop downloading now, 2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // otherwise, all favicon without sizes attribute are downloaded. 2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // - next candidate has sizes attribute and it is not larger than largest. 2840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch exact_match = image_urls_.size() == 1 || 2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_urls_[1].icon_sizes.empty() || 2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_urls_[1].icon_sizes[0].GetArea() < largest.GetArea(); 2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch exact_match = score == 1 || preferred_icon_size() == 0; 2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replace_best_favicon_candidate = 2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch exact_match || 2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch best_favicon_candidate_.icon_type == favicon_base::INVALID_ICON || 2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch score > best_favicon_candidate_.score; 2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (replace_best_favicon_candidate) { 295c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_ = FaviconCandidate( 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, image_url, image, score, icon_type); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return exact_match; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FaviconHandler::SetFavicon(const GURL& url, 3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& icon_url, 3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const gfx::Image& image, 3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 305a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (client_->GetFaviconService() && ShouldSaveFavicon(url)) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetHistoryFavicons(url, icon_url, icon_type, image); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (UrlMatches(url, url_) && icon_type == favicon_base::FAVICON) { 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!PageChangedSinceFaviconWasRequested()) 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetFaviconOnActivePage(icon_url, image); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FaviconHandler::SetFaviconOnActivePage(const std::vector< 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs( 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results, 3186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) favicon_base::GetFaviconScales(), 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_icon_size()); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The history service sends back results for a single icon URL, so it does 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not matter which result we get the |icon_url| from. 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL icon_url = favicon_bitmap_results.empty() ? 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL() : favicon_bitmap_results[0].icon_url; 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetFaviconOnActivePage(icon_url, resized_image); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FaviconHandler::SetFaviconOnActivePage(const GURL& icon_url, 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const gfx::Image& image) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No matter what happens, we need to mark the favicon as being set. 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->SetActiveFaviconValidity(true); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool icon_url_changed = driver_->GetActiveFaviconURL() != icon_url; 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->SetActiveFaviconURL(icon_url); 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image.IsEmpty()) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gfx::Image image_with_adjusted_colorspace = image; 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::SetFaviconColorSpace(&image_with_adjusted_colorspace); 340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->SetActiveFaviconImage(image_with_adjusted_colorspace); 342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NotifyFaviconUpdated(icon_url_changed); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::OnUpdateFaviconURL( 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<FaviconURL>& candidates) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.clear(); 348c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_ = FaviconCandidate(); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<FaviconURL>::const_iterator i = candidates.begin(); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != candidates.end(); ++i) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!i->icon_url.is_empty() && (i->icon_type & icon_types_)) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.push_back(*i); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!client_->GetFaviconService()) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (download_largest_icon_) 3590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SortAndPruneImageUrls(); 3600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(davemoore) Should clear on empty url. Currently we ignore it. 36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // This appears to be what FF does as well. 36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!image_urls_.empty()) 36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ProcessCurrentUrl(); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::ProcessCurrentUrl() { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!image_urls_.empty()); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // current_candidate() may return NULL if download_largest_icon_ is true and 3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // all the sizes are larger than the max. 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (PageChangedSinceFaviconWasRequested() || !current_candidate()) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_candidate()->icon_type == favicon_base::FAVICON) { 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!favicon_expired_or_incomplete_ && 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->GetActiveFaviconValidity() && 3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DoUrlAndIconMatch(*current_candidate(), 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->GetActiveFaviconURL(), 3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FAVICON)) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!favicon_expired_or_incomplete_ && got_favicon_from_history_ && 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasValidResult(history_results_) && 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoUrlsAndIconsMatch(*current_candidate(), history_results_)) { 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (got_favicon_from_history_) 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_url, 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_type); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::OnDidDownloadFavicon( 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<SkBitmap>& bitmaps, 398d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<gfx::Size>& original_bitmap_sizes) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadRequests::iterator i = download_requests_.find(id); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == download_requests_.end()) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently WebContents notifies us of ANY downloads so that it is 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // possible to get here. 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_candidate() && 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoUrlAndIconMatch(*current_candidate(), image_url, i->second.icon_type)) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool request_next_icon = true; 4090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch float score = 0.0f; 4100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::ImageSkia image_skia; 4110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (download_largest_icon_ && !bitmaps.empty()) { 4120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int index = -1; 4130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int max_size = GetMaximalIconSize(i->second.icon_type); 4140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Use the largest bitmap if FaviconURL doesn't have sizes attribute. 4150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (current_candidate()->icon_sizes.empty()) { 4160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index = GetLargestSizeIndex(original_bitmap_sizes, max_size * max_size); 4170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 4180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index = GetIndexBySize(original_bitmap_sizes, 4190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch current_candidate()->icon_sizes[0]); 4200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Find largest bitmap if there is no one exactly matched. 4210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index == -1) { 4220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index = GetLargestSizeIndex(original_bitmap_sizes, 4230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch max_size * max_size); 4240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index != -1) 4270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1)); 4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch image_skia = CreateFaviconImageSkia(bitmaps, 430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch original_bitmap_sizes, 431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch preferred_icon_size(), 432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &score); 4330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!image_skia.isNull()) { 4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::Image image(image_skia); 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The downloaded icon is still valid when there is no FaviconURL update 4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // during the downloading. 4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!bitmaps.empty()) { 4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_next_icon = !UpdateFaviconCandidate( 4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i->second.url, image_url, image, score, i->second.icon_type); 4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (request_next_icon && !PageChangedSinceFaviconWasRequested() && 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) image_urls_.size() > 1) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the first member of image_urls_ and process the remaining. 4470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_urls_.erase(image_urls_.begin()); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessCurrentUrl(); 4490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else if (best_favicon_candidate_.icon_type != 4500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::INVALID_ICON) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No more icons to request, set the favicon from the candidate. 452c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SetFavicon(best_favicon_candidate_.url, 453c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_.image_url, 454c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_.image, 455c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_.icon_type); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset candidate. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.clear(); 458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_ = FaviconCandidate(); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_.erase(i); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool FaviconHandler::PageChangedSinceFaviconWasRequested() { 465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (UrlMatches(driver_->GetActiveURL(), url_) && url_.is_valid()) { 466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL has changed out from under us (as will happen with redirects) 469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // return true. 470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint FaviconHandler::DownloadFavicon(const GURL& image_url, 474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int max_bitmap_size) { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_url.is_valid()) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return driver_->StartDownload(image_url, max_bitmap_size); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::UpdateFaviconMappingAndFetch( 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 4850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const favicon_base::FaviconResultsCallback& callback, 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): pass in all of |image_urls_| to 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // UpdateFaviconMappingsAndFetch(). 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<GURL> icon_urls; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls.push_back(icon_url); 492a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->UpdateFaviconMappingsAndFetch( 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_url, icon_urls, icon_type, preferred_icon_size(), callback, tracker); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 496c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::GetFaviconFromFaviconService( 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 4980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const favicon_base::FaviconResultsCallback& callback, 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 501a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->GetFavicon( 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url, icon_type, preferred_icon_size(), callback, tracker); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::GetFaviconForURLFromFaviconService( 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const favicon_base::FaviconResultsCallback& callback, 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) client_->GetFaviconService()->GetFaviconForPageURL( 511116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch page_url, 512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch icon_types, 513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch preferred_icon_size(), 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback, 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracker); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::SetHistoryFavicons(const GURL& page_url, 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 5200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& image) { 522a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->SetFavicons( 523a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch page_url, icon_url, icon_type, image); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FaviconHandler::ShouldSaveFavicon(const GURL& url) { 5275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!driver_->IsOffTheRecord()) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise store the favicon if the page is bookmarked. 5310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return client_->IsBookmarked(url); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 534d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void FaviconHandler::NotifyFaviconUpdated(bool icon_url_changed) { 5355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu driver_->NotifyFaviconUpdated(icon_url_changed); 536d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 537d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 538c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( 539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapResult>& 5400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_bitmap_results) { 541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (PageChangedSinceFaviconWasRequested()) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_favicon_from_history_ = true; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_results_ = favicon_bitmap_results; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_results = !favicon_bitmap_results.empty(); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_expired_or_incomplete_ = has_results && HasExpiredOrIncompleteResult( 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) preferred_icon_size(), favicon_bitmap_results); 5480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (has_results && icon_types_ == favicon_base::FAVICON && 549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !driver_->GetActiveFaviconValidity() && 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!current_candidate() || 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) { 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (HasValidResult(favicon_bitmap_results)) { 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The db knows the favicon (although it may be out of date) and the entry 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // doesn't have an icon. Set the favicon now, and if the favicon turns out 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to be expired (or the wrong url) we'll fetch later on. This way the 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // user doesn't see a flash of the default favicon. 557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetFaviconOnActivePage(favicon_bitmap_results); 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If |favicon_bitmap_results| does not have any valid results, treat the 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // favicon as if it's expired. 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(pkotwicz): Do something better. 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_expired_or_incomplete_ = true; 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_results && !favicon_expired_or_incomplete_) { 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_candidate() && 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)) { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mapping in the database is wrong. DownloadFavIconOrAskHistory will 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the mapping for this url and download the favicon if we don't 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already have it. 571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), 572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_url, 573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_type); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (current_candidate()) { 576c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // We know the official url for the favicon, but either don't have the 577c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // favicon or it's expired. Continue on to DownloadFaviconOrAskHistory to 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // either download or check history again. 579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), 580cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_url, 581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_type); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else we haven't got the icon url. When we get it we'll ask the 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // renderer to download the icon. 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 587c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::DownloadFaviconOrAskFaviconService( 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 5900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_expired_or_incomplete_) { 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have the mapping, but the favicon is out of date. Download it now. 593d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScheduleDownload(page_url, icon_url, icon_type); 594a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } else if (client_->GetFaviconService()) { 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't know the favicon, but we may have previously downloaded the 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon for another page that shares the same favicon. Ask for the 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon given the favicon URL. 5985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (driver_->IsOffTheRecord()) { 599c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetFaviconFromFaviconService( 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url, icon_type, 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ask the history service for the icon. This does two things: 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Attempts to fetch the favicon data from the database. 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. If the favicon exists in the database, this updates the database to 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // include the mapping between the page url and the favicon url. 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is asynchronous. The history service will call back when done. 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingAndFetch( 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_url, icon_url, icon_type, 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FaviconHandler::OnFaviconData(const std::vector< 618f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { 619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (PageChangedSinceFaviconWasRequested()) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_results = !favicon_bitmap_results.empty(); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult( 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) preferred_icon_size(), favicon_bitmap_results); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (has_results && icon_types_ == favicon_base::FAVICON) { 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasValidResult(favicon_bitmap_results)) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a favicon, set it now. If expired we'll download the current 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one again, but at least the user will get some icon instead of the 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default and most likely the current one is fine anyway. 631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetFaviconOnActivePage(favicon_bitmap_results); 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_expired_or_incomplete_result) { 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The favicon is out of date. Request the current one. 635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScheduleDownload(driver_->GetActiveURL(), 636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->GetActiveFaviconURL(), 637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) favicon_base::FAVICON); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (current_candidate() && 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!has_results || has_expired_or_incomplete_result || 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)))) { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't know the favicon, it is out of date or its type is not same as 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one got from page. Request the current one. 644cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScheduleDownload(driver_->GetActiveURL(), 645cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_url, 646cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_type); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_results_ = favicon_bitmap_results; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint FaviconHandler::ScheduleDownload(const GURL& url, 6520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& image_url, 6530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // A max bitmap size is specified to avoid receiving huge bitmaps in 6555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() 656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // for more details about the max bitmap size. 657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int download_id = DownloadFavicon(image_url, 658c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetMaximalIconSize(icon_type)); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (download_id) { 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Download ids should be unique. 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(download_requests_.find(download_id) == download_requests_.end()); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_[download_id] = 6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadRequest(url, image_url, icon_type); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return download_id; 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FaviconHandler::SortAndPruneImageUrls() { 6700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::vector<FaviconURL>::iterator i = image_urls_.begin(); 6710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != image_urls_.end();) { 6720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (i->icon_sizes.empty()) { 6730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i; 6740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch continue; 6750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int max_size = GetMaximalIconSize(i->icon_type); 6770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int index = GetLargestSizeIndex(i->icon_sizes, max_size * max_size); 6780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index == -1) { 6790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i = image_urls_.erase(i); 6800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 6810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::Size largest = i->icon_sizes[index]; 6820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i->icon_sizes.clear(); 6830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i->icon_sizes.push_back(largest); 6840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i; 6850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::stable_sort(image_urls_.begin(), image_urls_.end(), 6880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompareIconSize); 6890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 690