Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "android_webview/browser/icon_helper.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/hash.h"
     10 #include "base/logging.h"
     11 #include "content/public/browser/browser_thread.h"
     12 #include "content/public/browser/web_contents.h"
     13 #include "content/public/common/favicon_url.h"
     14 #include "third_party/skia/include/core/SkBitmap.h"
     15 #include "ui/gfx/size.h"
     16 
     17 using content::BrowserThread;
     18 using content::WebContents;
     19 
     20 namespace android_webview {
     21 
     22 IconHelper::IconHelper(WebContents* web_contents)
     23     : WebContentsObserver(web_contents),
     24       listener_(NULL),
     25       missing_favicon_urls_() {
     26 }
     27 
     28 IconHelper::~IconHelper() {
     29 }
     30 
     31 void IconHelper::SetListener(Listener* listener) {
     32   listener_ = listener;
     33 }
     34 
     35 void IconHelper::DownloadFaviconCallback(
     36     int id,
     37     int http_status_code,
     38     const GURL& image_url,
     39     const std::vector<SkBitmap>& bitmaps,
     40     const std::vector<gfx::Size>& original_bitmap_sizes) {
     41   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     42   if (http_status_code == 404) {
     43     MarkUnableToDownloadFavicon(image_url);
     44     return;
     45   }
     46 
     47   if (bitmaps.size() == 0) {
     48     return;
     49   }
     50 
     51   // We can protentially have multiple frames of the icon
     52   // in different sizes. We need more fine grain API spec
     53   // to let clients pick out the frame they want.
     54 
     55   // TODO(acleung): Pick the best icon to return based on size.
     56   if (listener_)
     57     listener_->OnReceivedIcon(image_url, bitmaps[0]);
     58 }
     59 
     60 void IconHelper::DidUpdateFaviconURL(
     61     const std::vector<content::FaviconURL>& candidates) {
     62   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     63   for (std::vector<content::FaviconURL>::const_iterator i = candidates.begin();
     64        i != candidates.end(); ++i) {
     65     if (!i->icon_url.is_valid())
     66       continue;
     67 
     68     switch(i->icon_type) {
     69       case content::FaviconURL::FAVICON:
     70         if ((listener_ && !listener_->ShouldDownloadFavicon(i->icon_url)) ||
     71             WasUnableToDownloadFavicon(i->icon_url)) {
     72           break;
     73         }
     74         web_contents()->DownloadImage(i->icon_url,
     75             true,  // Is a favicon
     76             0,  // No maximum size
     77             base::Bind(
     78                 &IconHelper::DownloadFaviconCallback, base::Unretained(this)));
     79         break;
     80       case content::FaviconURL::TOUCH_ICON:
     81         if (listener_)
     82           listener_->OnReceivedTouchIconUrl(i->icon_url.spec(), false);
     83         break;
     84       case content::FaviconURL::TOUCH_PRECOMPOSED_ICON:
     85         if (listener_)
     86           listener_->OnReceivedTouchIconUrl(i->icon_url.spec(), true);
     87         break;
     88       case content::FaviconURL::INVALID_ICON:
     89         // Silently ignore it. Only trigger a callback on valid icons.
     90         break;
     91       default:
     92         NOTREACHED();
     93         break;
     94     }
     95   }
     96 }
     97 
     98 void IconHelper::DidStartNavigationToPendingEntry(
     99     const GURL& url,
    100     content::NavigationController::ReloadType reload_type) {
    101   if (reload_type == content::NavigationController::RELOAD_IGNORING_CACHE)
    102     ClearUnableToDownloadFavicons();
    103 }
    104 
    105 void IconHelper::MarkUnableToDownloadFavicon(const GURL& icon_url) {
    106   MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
    107   missing_favicon_urls_.insert(url_hash);
    108 }
    109 
    110 bool IconHelper::WasUnableToDownloadFavicon(const GURL& icon_url) const {
    111   MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
    112   return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end();
    113 }
    114 
    115 void IconHelper::ClearUnableToDownloadFavicons() {
    116   missing_favicon_urls_.clear();
    117 }
    118 
    119 }  // namespace android_webview
    120