favicon_handler.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 "build/build_config.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted_memory.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/favicon_base/favicon_util.h" 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/favicon_base/select_favicon_frames.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/image_operations.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.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 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the scale factors in favicon_base::GetFaviconScaleFactors(). 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 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // of favicon_base::GetFaviconScaleFactors() 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) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<ui::ScaleFactor> scale_factors = 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::GetFaviconScaleFactors(); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < scale_factors.size(); ++i) { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int edge_size_in_pixel = floor( 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) desired_size_in_dip * ui::GetScaleForScaleFactor(scale_factors[i])); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(), 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.end(), gfx::Size(edge_size_in_pixel, edge_size_in_pixel)); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it == favicon_sizes.end()) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if at least one of |bitmap_results| is valid. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasValidResult( 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapResult>& bitmap_results) { 142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return std::find_if(bitmap_results.begin(), bitmap_results.end(), IsValid) != 143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bitmap_results.end(); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Returns the index of the entry with the largest area that is not larger than 1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// |max_area|; -1 if there is no such match. 1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint GetLargestSizeIndex(const std::vector<gfx::Size>& sizes, int max_area) { 1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!sizes.empty()); 1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int ret = -1; 1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (size_t i = 0; i < sizes.size(); ++i) { 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int area = sizes[i].GetArea(); 1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if ((ret == -1 || sizes[ret].GetArea() < area) && area <= max_area) 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ret = i; 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return ret; 1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Return the index of a size which is same as the given |size|, -1 returned if 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// there is no such bitmap. 1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint GetIndexBySize(const std::vector<gfx::Size>& sizes, 1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const gfx::Size& size) { 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!sizes.empty()); 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<gfx::Size>::const_iterator i = 1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::find(sizes.begin(), sizes.end(), size); 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (i == sizes.end()) 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return -1; 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return static_cast<int>(i - sizes.begin()); 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Compare function used for std::stable_sort to sort as descend. 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool CompareIconSize(const FaviconURL& b1, const FaviconURL& b2) { 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int area1 = 0; 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!b1.icon_sizes.empty()) 1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch area1 = b1.icon_sizes.front().GetArea(); 1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int area2 = 0; 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!b2.icon_sizes.empty()) 1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch area2 = b2.icon_sizes.front().GetArea(); 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return area1 > area2; 1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::DownloadRequest::DownloadRequest() 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : icon_type(favicon_base::INVALID_ICON) {} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::DownloadRequest::~DownloadRequest() { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::DownloadRequest::DownloadRequest( 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : url(url), image_url(image_url), icon_type(icon_type) {} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::FaviconCandidate::FaviconCandidate() 2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : score(0), icon_type(favicon_base::INVALID_ICON) {} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::FaviconCandidate::~FaviconCandidate() { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::FaviconCandidate::FaviconCandidate( 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& image, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score, 2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : url(url), 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_url(image_url), 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image(image), 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score(score), 2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_type(icon_type) {} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2230529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochFaviconHandler::FaviconHandler(FaviconClient* client, 2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FaviconDriver* driver, 2250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Type icon_type, 2260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool download_largest_icon) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : got_favicon_from_history_(false), 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_expired_or_incomplete_(false), 229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch icon_types_(icon_type == FAVICON 2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ? favicon_base::FAVICON 2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : favicon_base::TOUCH_ICON | 2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::TOUCH_PRECOMPOSED_ICON), 2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch download_largest_icon_(download_largest_icon), 234a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_(client), 2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu driver_(driver) { 2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(driver_); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::~FaviconHandler() { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::FetchFavicon(const GURL& url) { 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cancelable_task_tracker_.TryCancelAll(); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_ = url; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_expired_or_incomplete_ = got_favicon_from_history_ = false; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.clear(); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Request the favicon from the history service. In parallel to this the 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // renderer is going to notify us (well WebContents) when the favicon url is 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // available. 253a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (client_->GetFaviconService()) { 254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetFaviconForURLFromFaviconService( 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_, 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_types_, 257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind( 258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, 259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Unretained(this)), 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FaviconHandler::UpdateFaviconCandidate(const GURL& url, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& image, 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score, 2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool replace_best_favicon_candidate = false; 2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool exact_match = false; 2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (download_largest_icon_) { 2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replace_best_favicon_candidate = 2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image.Size().GetArea() > 2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch best_favicon_candidate_.image.Size().GetArea(); 2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::Size largest = best_favicon_candidate_.image.Size(); 2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (replace_best_favicon_candidate) 2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch largest = image.Size(); 2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // exact match (stop downloading next icon) only if 2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // - current candidate is only candidate. 2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // - next candidate doesn't have sizes attributes, in this case, the rest 2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // candidates don't have sizes attribute either, stop downloading now, 2840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // otherwise, all favicon without sizes attribute are downloaded. 2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // - next candidate has sizes attribute and it is not larger than largest. 2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch exact_match = image_urls_.size() == 1 || 2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_urls_[1].icon_sizes.empty() || 2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_urls_[1].icon_sizes[0].GetArea() < largest.GetArea(); 2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch exact_match = score == 1 || preferred_icon_size() == 0; 2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replace_best_favicon_candidate = 2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch exact_match || 2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch best_favicon_candidate_.icon_type == favicon_base::INVALID_ICON || 2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch score > best_favicon_candidate_.score; 2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (replace_best_favicon_candidate) { 297c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_ = FaviconCandidate( 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, image_url, image, score, icon_type); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return exact_match; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FaviconHandler::SetFavicon(const GURL& url, 3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& icon_url, 3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const gfx::Image& image, 3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 307a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (client_->GetFaviconService() && ShouldSaveFavicon(url)) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetHistoryFavicons(url, icon_url, icon_type, image); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (UrlMatches(url, url_) && icon_type == favicon_base::FAVICON) { 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!PageChangedSinceFaviconWasRequested()) 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetFaviconOnActivePage(icon_url, image); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FaviconHandler::SetFaviconOnActivePage(const std::vector< 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs( 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results, 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::GetFaviconScaleFactors(), 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_icon_size()); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The history service sends back results for a single icon URL, so it does 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not matter which result we get the |icon_url| from. 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL icon_url = favicon_bitmap_results.empty() ? 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL() : favicon_bitmap_results[0].icon_url; 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetFaviconOnActivePage(icon_url, resized_image); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FaviconHandler::SetFaviconOnActivePage(const GURL& icon_url, 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const gfx::Image& image) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No matter what happens, we need to mark the favicon as being set. 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->SetActiveFaviconValidity(true); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool icon_url_changed = driver_->GetActiveFaviconURL() != icon_url; 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->SetActiveFaviconURL(icon_url); 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image.IsEmpty()) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gfx::Image image_with_adjusted_colorspace = image; 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::SetFaviconColorSpace(&image_with_adjusted_colorspace); 342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->SetActiveFaviconImage(image_with_adjusted_colorspace); 344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NotifyFaviconUpdated(icon_url_changed); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::OnUpdateFaviconURL( 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<FaviconURL>& candidates) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.clear(); 350c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_ = FaviconCandidate(); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<FaviconURL>::const_iterator i = candidates.begin(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != candidates.end(); ++i) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!i->icon_url.is_empty() && (i->icon_type & icon_types_)) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.push_back(*i); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 357a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!client_->GetFaviconService()) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (download_largest_icon_) 3610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SortAndPruneImageUrls(); 3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(davemoore) Should clear on empty url. Currently we ignore it. 36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // This appears to be what FF does as well. 36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!image_urls_.empty()) 36646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ProcessCurrentUrl(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::ProcessCurrentUrl() { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!image_urls_.empty()); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // current_candidate() may return NULL if download_largest_icon_ is true and 3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // all the sizes are larger than the max. 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (PageChangedSinceFaviconWasRequested() || !current_candidate()) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_candidate()->icon_type == favicon_base::FAVICON) { 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!favicon_expired_or_incomplete_ && 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->GetActiveFaviconValidity() && 3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DoUrlAndIconMatch(*current_candidate(), 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->GetActiveFaviconURL(), 3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FAVICON)) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!favicon_expired_or_incomplete_ && got_favicon_from_history_ && 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasValidResult(history_results_) && 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoUrlsAndIconsMatch(*current_candidate(), history_results_)) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (got_favicon_from_history_) 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_url, 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_type); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::OnDidDownloadFavicon( 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 399d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<SkBitmap>& bitmaps, 400d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<gfx::Size>& original_bitmap_sizes) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadRequests::iterator i = download_requests_.find(id); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == download_requests_.end()) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently WebContents notifies us of ANY downloads so that it is 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // possible to get here. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_candidate() && 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoUrlAndIconMatch(*current_candidate(), image_url, i->second.icon_type)) { 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool request_next_icon = true; 4110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch float score = 0.0f; 4120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::ImageSkia image_skia; 4130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (download_largest_icon_ && !bitmaps.empty()) { 4140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int index = -1; 4150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int max_size = GetMaximalIconSize(i->second.icon_type); 4160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Use the largest bitmap if FaviconURL doesn't have sizes attribute. 4170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (current_candidate()->icon_sizes.empty()) { 4180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index = GetLargestSizeIndex(original_bitmap_sizes, max_size * max_size); 4190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 4200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index = GetIndexBySize(original_bitmap_sizes, 4210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch current_candidate()->icon_sizes[0]); 4220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Find largest bitmap if there is no one exactly matched. 4230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index == -1) { 4240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index = GetLargestSizeIndex(original_bitmap_sizes, 4250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch max_size * max_size); 4260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index != -1) 4290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1)); 4300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 4310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<ui::ScaleFactor> scale_factors = 432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::GetFaviconScaleFactors(); 4330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_skia = SelectFaviconFrames(bitmaps, 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch original_bitmap_sizes, 4350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scale_factors, 4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch preferred_icon_size(), 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &score); 4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!image_skia.isNull()) { 4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::Image image(image_skia); 4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The downloaded icon is still valid when there is no FaviconURL update 4430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // during the downloading. 4440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!bitmaps.empty()) { 4450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_next_icon = !UpdateFaviconCandidate( 4460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i->second.url, image_url, image, score, i->second.icon_type); 4470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (request_next_icon && !PageChangedSinceFaviconWasRequested() && 450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) image_urls_.size() > 1) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the first member of image_urls_ and process the remaining. 4520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_urls_.erase(image_urls_.begin()); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessCurrentUrl(); 4540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else if (best_favicon_candidate_.icon_type != 4550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::INVALID_ICON) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No more icons to request, set the favicon from the candidate. 457c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SetFavicon(best_favicon_candidate_.url, 458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_.image_url, 459c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_.image, 460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_.icon_type); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset candidate. 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.clear(); 463c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_ = FaviconCandidate(); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_.erase(i); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool FaviconHandler::PageChangedSinceFaviconWasRequested() { 470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (UrlMatches(driver_->GetActiveURL(), url_) && url_.is_valid()) { 471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL has changed out from under us (as will happen with redirects) 474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // return true. 475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint FaviconHandler::DownloadFavicon(const GURL& image_url, 479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int max_bitmap_size) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_url.is_valid()) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return driver_->StartDownload(image_url, max_bitmap_size); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::UpdateFaviconMappingAndFetch( 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 4900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const favicon_base::FaviconResultsCallback& callback, 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): pass in all of |image_urls_| to 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // UpdateFaviconMappingsAndFetch(). 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<GURL> icon_urls; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls.push_back(icon_url); 497a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->UpdateFaviconMappingsAndFetch( 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_url, icon_urls, icon_type, preferred_icon_size(), callback, tracker); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 501c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::GetFaviconFromFaviconService( 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 5030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const favicon_base::FaviconResultsCallback& callback, 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 506a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->GetFavicon( 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url, icon_type, preferred_icon_size(), callback, tracker); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 510c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::GetFaviconForURLFromFaviconService( 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const favicon_base::FaviconResultsCallback& callback, 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) client_->GetFaviconService()->GetFaviconForPageURL( 516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FaviconService::FaviconForPageURLParams( 517a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch page_url, icon_types, preferred_icon_size()), 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback, 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracker); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::SetHistoryFavicons(const GURL& page_url, 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 5240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& image) { 526a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->SetFavicons( 527a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch page_url, icon_url, icon_type, image); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FaviconHandler::ShouldSaveFavicon(const GURL& url) { 5315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!driver_->IsOffTheRecord()) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise store the favicon if the page is bookmarked. 5350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return client_->IsBookmarked(url); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 538d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void FaviconHandler::NotifyFaviconUpdated(bool icon_url_changed) { 5395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu driver_->NotifyFaviconUpdated(icon_url_changed); 540d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 541d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 542c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( 543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapResult>& 5440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_bitmap_results) { 545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (PageChangedSinceFaviconWasRequested()) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_favicon_from_history_ = true; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_results_ = favicon_bitmap_results; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_results = !favicon_bitmap_results.empty(); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_expired_or_incomplete_ = has_results && HasExpiredOrIncompleteResult( 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) preferred_icon_size(), favicon_bitmap_results); 5520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (has_results && icon_types_ == favicon_base::FAVICON && 553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !driver_->GetActiveFaviconValidity() && 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!current_candidate() || 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) { 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (HasValidResult(favicon_bitmap_results)) { 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The db knows the favicon (although it may be out of date) and the entry 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // doesn't have an icon. Set the favicon now, and if the favicon turns out 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to be expired (or the wrong url) we'll fetch later on. This way the 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // user doesn't see a flash of the default favicon. 561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetFaviconOnActivePage(favicon_bitmap_results); 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If |favicon_bitmap_results| does not have any valid results, treat the 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // favicon as if it's expired. 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(pkotwicz): Do something better. 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_expired_or_incomplete_ = true; 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_results && !favicon_expired_or_incomplete_) { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_candidate() && 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)) { 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mapping in the database is wrong. DownloadFavIconOrAskHistory will 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the mapping for this url and download the favicon if we don't 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already have it. 575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), 576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_url, 577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_type); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (current_candidate()) { 580c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // We know the official url for the favicon, but either don't have the 581c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // favicon or it's expired. Continue on to DownloadFaviconOrAskHistory to 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // either download or check history again. 583cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), 584cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_url, 585cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_type); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else we haven't got the icon url. When we get it we'll ask the 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // renderer to download the icon. 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 591c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::DownloadFaviconOrAskFaviconService( 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 5940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_expired_or_incomplete_) { 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have the mapping, but the favicon is out of date. Download it now. 597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScheduleDownload(page_url, icon_url, icon_type); 598a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } else if (client_->GetFaviconService()) { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't know the favicon, but we may have previously downloaded the 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon for another page that shares the same favicon. Ask for the 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon given the favicon URL. 6025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (driver_->IsOffTheRecord()) { 603c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetFaviconFromFaviconService( 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url, icon_type, 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), 6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ask the history service for the icon. This does two things: 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Attempts to fetch the favicon data from the database. 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. If the favicon exists in the database, this updates the database to 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // include the mapping between the page url and the favicon url. 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is asynchronous. The history service will call back when done. 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingAndFetch( 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_url, icon_url, icon_type, 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), 6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FaviconHandler::OnFaviconData(const std::vector< 622f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { 623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (PageChangedSinceFaviconWasRequested()) 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_results = !favicon_bitmap_results.empty(); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult( 6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) preferred_icon_size(), favicon_bitmap_results); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (has_results && icon_types_ == favicon_base::FAVICON) { 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasValidResult(favicon_bitmap_results)) { 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a favicon, set it now. If expired we'll download the current 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one again, but at least the user will get some icon instead of the 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default and most likely the current one is fine anyway. 635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetFaviconOnActivePage(favicon_bitmap_results); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_expired_or_incomplete_result) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The favicon is out of date. Request the current one. 639cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScheduleDownload(driver_->GetActiveURL(), 640cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) driver_->GetActiveFaviconURL(), 641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) favicon_base::FAVICON); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (current_candidate() && 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!has_results || has_expired_or_incomplete_result || 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)))) { 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't know the favicon, it is out of date or its type is not same as 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one got from page. Request the current one. 648cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScheduleDownload(driver_->GetActiveURL(), 649cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_url, 650cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_candidate()->icon_type); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_results_ = favicon_bitmap_results; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint FaviconHandler::ScheduleDownload(const GURL& url, 6560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& image_url, 6570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // A max bitmap size is specified to avoid receiving huge bitmaps in 6595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() 660d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // for more details about the max bitmap size. 661d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int download_id = DownloadFavicon(image_url, 662c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetMaximalIconSize(icon_type)); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (download_id) { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Download ids should be unique. 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(download_requests_.find(download_id) == download_requests_.end()); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_[download_id] = 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadRequest(url, image_url, icon_type); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return download_id; 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 6730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FaviconHandler::SortAndPruneImageUrls() { 6740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::vector<FaviconURL>::iterator i = image_urls_.begin(); 6750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != image_urls_.end();) { 6760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (i->icon_sizes.empty()) { 6770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i; 6780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch continue; 6790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 680cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int max_size = GetMaximalIconSize(i->icon_type); 6810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int index = GetLargestSizeIndex(i->icon_sizes, max_size * max_size); 6820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index == -1) { 6830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i = image_urls_.erase(i); 6840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 6850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::Size largest = i->icon_sizes[index]; 6860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i->icon_sizes.clear(); 6870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i->icon_sizes.push_back(largest); 6880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i; 6890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 6910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::stable_sort(image_urls_.begin(), image_urls_.end(), 6920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompareIconSize); 6930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 694