favicon_handler.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_util.h" 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/favicon_base/select_favicon_frames.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/favicon_status.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.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.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_util.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::FaviconURL; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Size (along each axis) of a touch icon. This currently corresponds to 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the apple touch icon for iPad. 331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kTouchIconSize = 144; 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Returns favicon_base::IconType the given icon_type corresponds to. 360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochfavicon_base::IconType ToChromeIconType(FaviconURL::IconType icon_type) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (icon_type) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FaviconURL::FAVICON: 390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return favicon_base::FAVICON; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FaviconURL::TOUCH_ICON: 410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return favicon_base::TOUCH_ICON; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FaviconURL::TOUCH_PRECOMPOSED_ICON: 430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return favicon_base::TOUCH_PRECOMPOSED_ICON; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FaviconURL::INVALID_ICON: 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return favicon_base::INVALID_ICON; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return favicon_base::INVALID_ICON; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Get the maximal icon size in pixels for a icon of type |icon_type| for the 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// current platform. 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint GetMaximalIconSize(favicon_base::IconType icon_type) { 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (icon_type) { 550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case favicon_base::FAVICON: 561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#if defined(OS_ANDROID) 571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 192; 581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#else 591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return gfx::ImageSkia::GetMaxSupportedScale() * gfx::kFaviconSize; 601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif 610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case favicon_base::TOUCH_ICON: 620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case favicon_base::TOUCH_PRECOMPOSED_ICON: 631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return kTouchIconSize; 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case favicon_base::INVALID_ICON: 651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 0; 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NOTREACHED(); 681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 0; 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DoUrlAndIconMatch(const FaviconURL& favicon_url, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return favicon_url.icon_url == url && 75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ToChromeIconType(favicon_url.icon_type) == icon_type; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if all of the icon URLs and icon types in |bitmap_results| are 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// identical and if they match the icon URL and icon type in |favicon_url|. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns false if |bitmap_results| is empty. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DoUrlsAndIconsMatch( 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FaviconURL& favicon_url, 830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconBitmapResult>& bitmap_results) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap_results.empty()) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const favicon_base::IconType icon_type = 880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ToChromeIconType(favicon_url.icon_type); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bitmap_results.size(); ++i) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_url.icon_url != bitmap_results[i].icon_url || 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_type != bitmap_results[i].icon_type) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string UrlWithoutFragment(const GURL& gurl) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL::Replacements replacements; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) replacements.ClearRef(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gurl.ReplaceComponents(replacements).spec(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UrlMatches(const GURL& gurl_a, const GURL& gurl_b) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UrlWithoutFragment(gurl_a) == UrlWithoutFragment(gurl_b); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return true if |bitmap_result| is expired. 1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool IsExpired(const favicon_base::FaviconBitmapResult& bitmap_result) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bitmap_result.expired; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return true if |bitmap_result| is valid. 1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool IsValid(const favicon_base::FaviconBitmapResult& bitmap_result) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bitmap_result.is_valid(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if at least one of the bitmaps in |bitmap_results| is expired or 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// if |bitmap_results| is missing favicons for |desired_size_in_dip| and one of 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the scale factors in FaviconUtil::GetFaviconScaleFactors(). 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasExpiredOrIncompleteResult( 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int desired_size_in_dip, 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconBitmapResult>& bitmap_results) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if at least one of the bitmaps is expired. 1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconBitmapResult>::const_iterator it = 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find_if(bitmap_results.begin(), bitmap_results.end(), IsExpired); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != bitmap_results.end()) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Any favicon size is good if the desired size is 0. 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (desired_size_in_dip == 0) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if the favicon for at least one of the scale factors is missing. 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |bitmap_results| should always be complete for data inserted by 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // FaviconHandler as the FaviconHandler stores favicons resized to all 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of FaviconUtil::GetFaviconScaleFactors() into the history backend. 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Examples of when |bitmap_results| can be incomplete: 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - Favicons inserted into the history backend by sync. 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - Favicons for imported bookmarks. 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size> favicon_sizes; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bitmap_results.size(); ++i) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmap_results[i].pixel_size); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<ui::ScaleFactor> scale_factors = 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconUtil::GetFaviconScaleFactors(); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < scale_factors.size(); ++i) { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int edge_size_in_pixel = floor( 15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) desired_size_in_dip * ui::GetImageScale(scale_factors[i])); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(), 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.end(), gfx::Size(edge_size_in_pixel, edge_size_in_pixel)); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it == favicon_sizes.end()) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if at least one of |bitmap_results| is valid. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasValidResult( 1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconBitmapResult>& bitmap_results) { 162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return std::find_if(bitmap_results.begin(), bitmap_results.end(), IsValid) != 163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bitmap_results.end(); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Returns the index of the entry with the largest area that is not larger than 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// |max_area|; -1 if there is no such match. 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint GetLargestSizeIndex(const std::vector<gfx::Size>& sizes, int max_area) { 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!sizes.empty()); 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int ret = -1; 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (size_t i = 0; i < sizes.size(); ++i) { 1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int area = sizes[i].GetArea(); 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if ((ret == -1 || sizes[ret].GetArea() < area) && area <= max_area) 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ret = i; 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return ret; 1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Return the index of a size which is same as the given |size|, -1 returned if 1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// there is no such bitmap. 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint GetIndexBySize(const std::vector<gfx::Size>& sizes, 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const gfx::Size& size) { 1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!sizes.empty()); 1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<gfx::Size>::const_iterator i = 1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::find(sizes.begin(), sizes.end(), size); 1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (i == sizes.end()) 1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return -1; 1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return static_cast<int>(i - sizes.begin()); 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Compare function used for std::stable_sort to sort as descend. 1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool CompareIconSize(const FaviconURL& b1, const FaviconURL& b2) { 1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int area1 = 0; 1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!b1.icon_sizes.empty()) 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch area1 = b1.icon_sizes.front().GetArea(); 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int area2 = 0; 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!b2.icon_sizes.empty()) 2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch area2 = b2.icon_sizes.front().GetArea(); 2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return area1 > area2; 2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::DownloadRequest::DownloadRequest() 2100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : icon_type(favicon_base::INVALID_ICON) {} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::DownloadRequest::~DownloadRequest() { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::DownloadRequest::DownloadRequest( 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 2180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) 2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : url(url), image_url(image_url), icon_type(icon_type) {} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::FaviconCandidate::FaviconCandidate() 2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : score(0), icon_type(favicon_base::INVALID_ICON) {} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::FaviconCandidate::~FaviconCandidate() { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::FaviconCandidate::FaviconCandidate( 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& image, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score, 2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : url(url), 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_url(image_url), 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image(image), 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score(score), 2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_type(icon_type) {} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2430529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochFaviconHandler::FaviconHandler(FaviconClient* client, 2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FaviconDriver* driver, 2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Type icon_type, 2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool download_largest_icon) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : got_favicon_from_history_(false), 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_expired_or_incomplete_(false), 249a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch icon_types_(icon_type == FAVICON 2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ? favicon_base::FAVICON 2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : favicon_base::TOUCH_ICON | 2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::TOUCH_PRECOMPOSED_ICON), 2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch download_largest_icon_(download_largest_icon), 254a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_(client), 2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu driver_(driver) { 2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(driver_); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconHandler::~FaviconHandler() { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::FetchFavicon(const GURL& url) { 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cancelable_task_tracker_.TryCancelAll(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_ = url; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_expired_or_incomplete_ = got_favicon_from_history_ = false; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.clear(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Request the favicon from the history service. In parallel to this the 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // renderer is going to notify us (well WebContents) when the favicon url is 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // available. 273a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (client_->GetFaviconService()) { 274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetFaviconForURLFromFaviconService( 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_types_, 277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind( 278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, 279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Unretained(this)), 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FaviconHandler::UpdateFaviconCandidate(const GURL& url, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& image, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score, 2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool replace_best_favicon_candidate = false; 2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool exact_match = false; 2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (download_largest_icon_) { 2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replace_best_favicon_candidate = 2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image.Size().GetArea() > 2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch best_favicon_candidate_.image.Size().GetArea(); 2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::Size largest = best_favicon_candidate_.image.Size(); 2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (replace_best_favicon_candidate) 2980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch largest = image.Size(); 2990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // exact match (stop downloading next icon) only if 3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // - current candidate is only candidate. 3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // - next candidate doesn't have sizes attributes, in this case, the rest 3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // candidates don't have sizes attribute either, stop downloading now, 3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // otherwise, all favicon without sizes attribute are downloaded. 3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // - next candidate has sizes attribute and it is not larger than largest. 3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch exact_match = image_urls_.size() == 1 || 3070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_urls_[1].icon_sizes.empty() || 3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_urls_[1].icon_sizes[0].GetArea() < largest.GetArea(); 3090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch exact_match = score == 1 || preferred_icon_size() == 0; 3110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replace_best_favicon_candidate = 3120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch exact_match || 3130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch best_favicon_candidate_.icon_type == favicon_base::INVALID_ICON || 3140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch score > best_favicon_candidate_.score; 3150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (replace_best_favicon_candidate) { 317c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_ = FaviconCandidate( 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, image_url, image, score, icon_type); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return exact_match; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FaviconHandler::SetFavicon(const GURL& url, 3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& icon_url, 3250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const gfx::Image& image, 3260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 327a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (client_->GetFaviconService() && ShouldSaveFavicon(url)) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetHistoryFavicons(url, icon_url, icon_type, image); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (UrlMatches(url, url_) && icon_type == favicon_base::FAVICON) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationEntry* entry = GetEntry(); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry) 333c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SetFaviconOnNavigationEntry(entry, icon_url, image); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 337c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::SetFaviconOnNavigationEntry( 338c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch NavigationEntry* entry, 3390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconBitmapResult>& 3400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_bitmap_results) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Image resized_image = FaviconUtil::SelectFaviconFramesFromPNGs( 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results, 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconUtil::GetFaviconScaleFactors(), 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_icon_size()); 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The history service sends back results for a single icon URL, so it does 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not matter which result we get the |icon_url| from. 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL icon_url = favicon_bitmap_results.empty() ? 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL() : favicon_bitmap_results[0].icon_url; 349c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SetFaviconOnNavigationEntry(entry, icon_url, resized_image); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 352c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::SetFaviconOnNavigationEntry( 353c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch NavigationEntry* entry, 354c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const GURL& icon_url, 355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const gfx::Image& image) { 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No matter what happens, we need to mark the favicon as being set. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->GetFavicon().valid = true; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool icon_url_changed = (entry->GetFavicon().url != icon_url); 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry->GetFavicon().url = icon_url; 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image.IsEmpty()) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gfx::Image image_with_adjusted_colorspace = image; 366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FaviconUtil::SetFaviconColorSpace(&image_with_adjusted_colorspace); 367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch entry->GetFavicon().image = image_with_adjusted_colorspace; 369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NotifyFaviconUpdated(icon_url_changed); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::OnUpdateFaviconURL( 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 page_id, 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<FaviconURL>& candidates) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.clear(); 376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_ = FaviconCandidate(); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<FaviconURL>::const_iterator i = candidates.begin(); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != candidates.end(); ++i) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!i->icon_url.is_empty() && (i->icon_type & icon_types_)) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.push_back(*i); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(davemoore) Should clear on empty url. Currently we ignore it. 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This appears to be what FF does as well. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_urls_.empty()) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 388a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!client_->GetFaviconService()) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (download_largest_icon_) 3920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SortAndPruneImageUrls(); 3930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessCurrentUrl(); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::ProcessCurrentUrl() { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!image_urls_.empty()); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationEntry* entry = GetEntry(); 4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // current_candidate() may return NULL if download_largest_icon_ is true and 4030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // all the sizes are larger than the max. 4040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!entry || !current_candidate()) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_candidate()->icon_type == FaviconURL::FAVICON) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_expired_or_incomplete_ && entry->GetFavicon().valid && 4090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DoUrlAndIconMatch(*current_candidate(), 4100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch entry->GetFavicon().url, 4110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FAVICON)) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!favicon_expired_or_incomplete_ && got_favicon_from_history_ && 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasValidResult(history_results_) && 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoUrlsAndIconsMatch(*current_candidate(), history_results_)) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (got_favicon_from_history_) 420c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DownloadFaviconOrAskFaviconService( 421c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch entry->GetURL(), current_candidate()->icon_url, 422c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ToChromeIconType(current_candidate()->icon_type)); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::OnDidDownloadFavicon( 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 428d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<SkBitmap>& bitmaps, 429d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<gfx::Size>& original_bitmap_sizes) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadRequests::iterator i = download_requests_.find(id); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == download_requests_.end()) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently WebContents notifies us of ANY downloads so that it is 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // possible to get here. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_candidate() && 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoUrlAndIconMatch(*current_candidate(), image_url, i->second.icon_type)) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool request_next_icon = true; 4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch float score = 0.0f; 4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::ImageSkia image_skia; 4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (download_largest_icon_ && !bitmaps.empty()) { 4430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int index = -1; 4440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int max_size = GetMaximalIconSize(i->second.icon_type); 4450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Use the largest bitmap if FaviconURL doesn't have sizes attribute. 4460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (current_candidate()->icon_sizes.empty()) { 4470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index = GetLargestSizeIndex(original_bitmap_sizes, max_size * max_size); 4480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 4490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index = GetIndexBySize(original_bitmap_sizes, 4500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch current_candidate()->icon_sizes[0]); 4510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Find largest bitmap if there is no one exactly matched. 4520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index == -1) { 4530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index = GetLargestSizeIndex(original_bitmap_sizes, 4540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch max_size * max_size); 4550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index != -1) 4580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1)); 4590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 4600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<ui::ScaleFactor> scale_factors = 4610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FaviconUtil::GetFaviconScaleFactors(); 4620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_skia = SelectFaviconFrames(bitmaps, 4630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch original_bitmap_sizes, 4640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scale_factors, 4650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch preferred_icon_size(), 4660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &score); 4670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!image_skia.isNull()) { 4700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::Image image(image_skia); 4710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The downloaded icon is still valid when there is no FaviconURL update 4720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // during the downloading. 4730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!bitmaps.empty()) { 4740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_next_icon = !UpdateFaviconCandidate( 4750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i->second.url, image_url, image, score, i->second.icon_type); 4760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request_next_icon && GetEntry() && image_urls_.size() > 1) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the first member of image_urls_ and process the remaining. 4800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch image_urls_.erase(image_urls_.begin()); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessCurrentUrl(); 4820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else if (best_favicon_candidate_.icon_type != 4830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::INVALID_ICON) { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No more icons to request, set the favicon from the candidate. 485c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SetFavicon(best_favicon_candidate_.url, 486c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_.image_url, 487c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_.image, 488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_.icon_type); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset candidate. 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_urls_.clear(); 491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch best_favicon_candidate_ = FaviconCandidate(); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_.erase(i); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NavigationEntry* FaviconHandler::GetEntry() { 4985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu NavigationEntry* entry = driver_->GetActiveEntry(); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry && UrlMatches(entry->GetURL(), url_)) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entry; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL has changed out from under us (as will happen with redirects) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return NULL. 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint FaviconHandler::DownloadFavicon(const GURL& image_url, 508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int max_bitmap_size) { 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_url.is_valid()) { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return driver_->StartDownload(image_url, max_bitmap_size); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::UpdateFaviconMappingAndFetch( 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 5190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const FaviconService::FaviconResultsCallback& callback, 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): pass in all of |image_urls_| to 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // UpdateFaviconMappingsAndFetch(). 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<GURL> icon_urls; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls.push_back(icon_url); 526a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->UpdateFaviconMappingsAndFetch( 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_url, icon_urls, icon_type, preferred_icon_size(), callback, tracker); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 530c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::GetFaviconFromFaviconService( 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 5320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const FaviconService::FaviconResultsCallback& callback, 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 535a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->GetFavicon( 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url, icon_type, preferred_icon_size(), callback, tracker); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 539c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::GetFaviconForURLFromFaviconService( 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const FaviconService::FaviconResultsCallback& callback, 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 544a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->GetFaviconForURL( 545a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch FaviconService::FaviconForURLParams( 546a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch page_url, icon_types, preferred_icon_size()), 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback, 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracker); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconHandler::SetHistoryFavicons(const GURL& page_url, 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 5530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& image) { 555a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch client_->GetFaviconService()->SetFavicons( 556a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch page_url, icon_url, icon_type, image); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FaviconHandler::ShouldSaveFavicon(const GURL& url) { 5605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!driver_->IsOffTheRecord()) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise store the favicon if the page is bookmarked. 5640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return client_->IsBookmarked(url); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 567d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void FaviconHandler::NotifyFaviconUpdated(bool icon_url_changed) { 5685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu driver_->NotifyFaviconUpdated(icon_url_changed); 569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 571c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( 5720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconBitmapResult>& 5730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_bitmap_results) { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationEntry* entry = GetEntry(); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_favicon_from_history_ = true; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_results_ = favicon_bitmap_results; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_results = !favicon_bitmap_results.empty(); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_expired_or_incomplete_ = has_results && HasExpiredOrIncompleteResult( 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) preferred_icon_size(), favicon_bitmap_results); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (has_results && icon_types_ == favicon_base::FAVICON && 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !entry->GetFavicon().valid && 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!current_candidate() || 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) { 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (HasValidResult(favicon_bitmap_results)) { 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The db knows the favicon (although it may be out of date) and the entry 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // doesn't have an icon. Set the favicon now, and if the favicon turns out 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to be expired (or the wrong url) we'll fetch later on. This way the 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // user doesn't see a flash of the default favicon. 594c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SetFaviconOnNavigationEntry(entry, favicon_bitmap_results); 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If |favicon_bitmap_results| does not have any valid results, treat the 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // favicon as if it's expired. 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(pkotwicz): Do something better. 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_expired_or_incomplete_ = true; 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_results && !favicon_expired_or_incomplete_) { 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_candidate() && 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)) { 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mapping in the database is wrong. DownloadFavIconOrAskHistory will 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the mapping for this url and download the favicon if we don't 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already have it. 609c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DownloadFaviconOrAskFaviconService( 610c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch entry->GetURL(), current_candidate()->icon_url, 611c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ToChromeIconType(current_candidate()->icon_type)); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (current_candidate()) { 614c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // We know the official url for the favicon, but either don't have the 615c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // favicon or it's expired. Continue on to DownloadFaviconOrAskHistory to 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // either download or check history again. 617c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DownloadFaviconOrAskFaviconService( 618c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch entry->GetURL(), current_candidate()->icon_url, 619c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ToChromeIconType(current_candidate()->icon_type)); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else we haven't got the icon url. When we get it we'll ask the 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // renderer to download the icon. 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid FaviconHandler::DownloadFaviconOrAskFaviconService( 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url, 6280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_expired_or_incomplete_) { 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have the mapping, but the favicon is out of date. Download it now. 631d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScheduleDownload(page_url, icon_url, icon_type); 632a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } else if (client_->GetFaviconService()) { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't know the favicon, but we may have previously downloaded the 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon for another page that shares the same favicon. Ask for the 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon given the favicon URL. 6365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (driver_->IsOffTheRecord()) { 637c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetFaviconFromFaviconService( 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url, icon_type, 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), 6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ask the history service for the icon. This does two things: 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Attempts to fetch the favicon data from the database. 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. If the favicon exists in the database, this updates the database to 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // include the mapping between the page url and the favicon url. 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is asynchronous. The history service will call back when done. 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingAndFetch( 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_url, icon_url, icon_type, 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FaviconHandler::OnFaviconData(const std::vector< 6560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconBitmapResult>& favicon_bitmap_results) { 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationEntry* entry = GetEntry(); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_results = !favicon_bitmap_results.empty(); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult( 6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) preferred_icon_size(), favicon_bitmap_results); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (has_results && icon_types_ == favicon_base::FAVICON) { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasValidResult(favicon_bitmap_results)) { 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a favicon, set it now. If expired we'll download the current 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one again, but at least the user will get some icon instead of the 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default and most likely the current one is fine anyway. 670c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SetFaviconOnNavigationEntry(entry, favicon_bitmap_results); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_expired_or_incomplete_result) { 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The favicon is out of date. Request the current one. 6740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ScheduleDownload( 6750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch entry->GetURL(), entry->GetFavicon().url, favicon_base::FAVICON); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (current_candidate() && 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!has_results || has_expired_or_incomplete_result || 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)))) { 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't know the favicon, it is out of date or its type is not same as 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one got from page. Request the current one. 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleDownload(entry->GetURL(), current_candidate()->icon_url, 683c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ToChromeIconType(current_candidate()->icon_type)); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_results_ = favicon_bitmap_results; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint FaviconHandler::ScheduleDownload(const GURL& url, 6890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& image_url, 6900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type) { 691d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // A max bitmap size is specified to avoid receiving huge bitmaps in 6925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() 693d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // for more details about the max bitmap size. 694d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int download_id = DownloadFavicon(image_url, 695c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetMaximalIconSize(icon_type)); 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (download_id) { 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Download ids should be unique. 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(download_requests_.find(download_id) == download_requests_.end()); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_[download_id] = 7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadRequest(url, image_url, icon_type); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return download_id; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid FaviconHandler::SortAndPruneImageUrls() { 7070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::vector<FaviconURL>::iterator i = image_urls_.begin(); 7080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i != image_urls_.end();) { 7090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (i->icon_sizes.empty()) { 7100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i; 7110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch continue; 7120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int max_size = GetMaximalIconSize(ToChromeIconType(i->icon_type)); 7140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int index = GetLargestSizeIndex(i->icon_sizes, max_size * max_size); 7150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (index == -1) { 7160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i = image_urls_.erase(i); 7170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 7180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::Size largest = i->icon_sizes[index]; 7190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i->icon_sizes.clear(); 7200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch i->icon_sizes.push_back(largest); 7210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++i; 7220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::stable_sort(image_urls_.begin(), image_urls_.end(), 7250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompareIconSize); 7260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 727