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/ui/ash/launcher/launcher_favicon_loader.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shelf/shelf_constants.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/weak_ptr.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents_observer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxBitmapSize = 256; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// FaviconRawBitmapHandler fetchs all bitmaps with the 'icon' (or 'shortcut 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// icon') 23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// link tag, storing the one that best matches ash::kShelfSize. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These icon bitmaps are not resized and are not cached beyond the lifetime 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the class. Bitmaps larger than kMaxBitmapSize are ignored. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class FaviconRawBitmapHandler : public content::WebContentsObserver { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FaviconRawBitmapHandler(content::WebContents* web_contents, 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LauncherFaviconLoader::Delegate* delegate) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : content::WebContentsObserver(web_contents), 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_(delegate), 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_(this) {} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual ~FaviconRawBitmapHandler() {} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap& bitmap() const { return bitmap_; } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool HasPendingDownloads() const; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // content::WebContentObserver implementation. 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void DidUpdateFaviconURL( 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<content::FaviconURL>& candidates) OVERRIDE; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void DidDownloadFavicon( 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int id, 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int http_status_code, 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& image_url, 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<SkBitmap>& bitmaps, 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<gfx::Size>& original_bitmap_sizes); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddFavicon(const GURL& image_url, const SkBitmap& new_bitmap); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LauncherFaviconLoader::Delegate* delegate_; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::set<GURL> UrlSet; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Map of pending download urls. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlSet pending_requests_; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Map of processed urls. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlSet processed_requests_; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current bitmap and source url. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap bitmap_; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL bitmap_url_; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::WeakPtrFactory<FaviconRawBitmapHandler> weak_ptr_factory_; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FaviconRawBitmapHandler); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void FaviconRawBitmapHandler::DidUpdateFaviconURL( 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<content::FaviconURL>& candidates) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function receives a complete list of faviocn urls for the page. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It may get called multiple times with the same list, and will also get 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called any time an item is added or removed. As such, we track processed 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and pending urls, but only until they are removed from the list. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlSet new_pending, new_processed; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a map of valid favicon urls. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<GURL> urls; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<content::FaviconURL>::const_iterator iter; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (iter = candidates.begin(); iter != candidates.end(); ++iter) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter->icon_type != content::FaviconURL::FAVICON) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url = iter->icon_url; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.is_valid()) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls.insert(url); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Preserve matching pending requests amd processed requests. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_requests_.find(url) != pending_requests_.end()) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_pending.insert(url); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (processed_requests_.find(url) != processed_requests_.end()) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_processed.insert(url); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_requests_ = new_pending; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_requests_ = new_processed; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset bitmap_ if no longer valid (i.e. not in the list of urls). 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (urls.find(bitmap_url_) == urls.end()) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_url_ = GURL(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_.reset(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Request any new urls. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::iterator iter = urls.begin(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != urls.end(); ++iter) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (processed_requests_.find(*iter) != processed_requests_.end()) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Skip already processed downloads. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_requests_.find(*iter) != pending_requests_.end()) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Skip already pending downloads. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_requests_.insert(*iter); 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_contents()->DownloadImage( 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *iter, 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch true, // is a favicon 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0, // no maximum size 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&FaviconRawBitmapHandler::DidDownloadFavicon, 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool FaviconRawBitmapHandler::HasPendingDownloads() const { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !pending_requests_.empty(); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void FaviconRawBitmapHandler::DidDownloadFavicon( 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int http_status_code, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& image_url, 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<SkBitmap>& bitmaps, 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<gfx::Size>& original_bitmap_sizes) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlSet::iterator iter = pending_requests_.find(image_url); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter == pending_requests_.end()) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updates are received for all downloads; ignore unrequested urls. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_requests_.erase(iter); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Favicon bitmaps are ordered by decreasing width. 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!bitmaps.empty()) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddFavicon(image_url, bitmaps[0]); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void FaviconRawBitmapHandler::AddFavicon(const GURL& image_url, 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const SkBitmap& new_bitmap) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_requests_.insert(image_url); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_bitmap.height() > kMaxBitmapSize || 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_bitmap.width() > kMaxBitmapSize) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (new_bitmap.height() < ash::kShelfSize) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bitmap_.isNull()) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want the smallest icon that is large enough. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_bitmap.height() > bitmap_.height()) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_url_ = image_url; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_ = new_bitmap; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->FaviconUpdated(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace internal 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LauncherFaviconLoader::LauncherFaviconLoader(Delegate* delegate, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* web_contents) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : web_contents_(web_contents) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_handler_.reset( 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new internal::FaviconRawBitmapHandler(web_contents, delegate)); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LauncherFaviconLoader::~LauncherFaviconLoader() { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkBitmap LauncherFaviconLoader::GetFavicon() const { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return favicon_handler_->bitmap(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LauncherFaviconLoader::HasPendingDownloads() const { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return favicon_handler_->HasPendingDownloads(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 178