12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "android_webview/browser/icon_helper.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h" 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/hash.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/favicon_url.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/size.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread; 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::WebContents; 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace android_webview { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IconHelper::IconHelper(WebContents* web_contents) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : WebContentsObserver(web_contents), 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu listener_(NULL), 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu missing_favicon_urls_() { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IconHelper::~IconHelper() { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IconHelper::SetListener(Listener* listener) { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener_ = listener; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IconHelper::DownloadFaviconCallback( 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int id, 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int http_status_code, 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const GURL& image_url, 39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<SkBitmap>& bitmaps, 40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<gfx::Size>& original_bitmap_sizes) { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (http_status_code == 404) { 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MarkUnableToDownloadFavicon(image_url); 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmaps.size() == 0) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We can protentially have multiple frames of the icon 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in different sizes. We need more fine grain API spec 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to let clients pick out the frame they want. 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(acleung): Pick the best icon to return based on size. 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (listener_) 57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch listener_->OnReceivedIcon(image_url, bitmaps[0]); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void IconHelper::DidUpdateFaviconURL( 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<content::FaviconURL>& candidates) { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<content::FaviconURL>::const_iterator i = candidates.begin(); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i != candidates.end(); ++i) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!i->icon_url.is_valid()) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch(i->icon_type) { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::FaviconURL::FAVICON: 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if ((listener_ && !listener_->ShouldDownloadFavicon(i->icon_url)) || 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WasUnableToDownloadFavicon(i->icon_url)) { 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_contents()->DownloadImage(i->icon_url, 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch true, // Is a favicon 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0, // No maximum size 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind( 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &IconHelper::DownloadFaviconCallback, base::Unretained(this))); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::FaviconURL::TOUCH_ICON: 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (listener_) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener_->OnReceivedTouchIconUrl(i->icon_url.spec(), false); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::FaviconURL::TOUCH_PRECOMPOSED_ICON: 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (listener_) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener_->OnReceivedTouchIconUrl(i->icon_url.spec(), true); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::FaviconURL::INVALID_ICON: 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Silently ignore it. Only trigger a callback on valid icons. 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid IconHelper::DidStartNavigationToPendingEntry( 995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const GURL& url, 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content::NavigationController::ReloadType reload_type) { 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (reload_type == content::NavigationController::RELOAD_IGNORING_CACHE) 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ClearUnableToDownloadFavicons(); 1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid IconHelper::MarkUnableToDownloadFavicon(const GURL& icon_url) { 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MissingFaviconURLHash url_hash = base::Hash(icon_url.spec()); 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu missing_favicon_urls_.insert(url_hash); 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool IconHelper::WasUnableToDownloadFavicon(const GURL& icon_url) const { 1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MissingFaviconURLHash url_hash = base::Hash(icon_url.spec()); 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end(); 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid IconHelper::ClearUnableToDownloadFavicons() { 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu missing_favicon_urls_.clear(); 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace android_webview 120