Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / favicon / favicon_handler.cc
index 3785bbc..addf93b 100644 (file)
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ref_counted_memory.h"
-#include "chrome/browser/bookmarks/bookmark_service.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
 #include "chrome/browser/favicon/favicon_util.h"
-#include "chrome/browser/history/select_favicon_frames.h"
-#include "chrome/browser/profiles/profile.h"
+#include "components/favicon_base/select_favicon_frames.h"
 #include "content/public/browser/favicon_status.h"
 #include "content/public/browser/navigation_entry.h"
 #include "skia/ext/image_operations.h"
@@ -34,36 +32,36 @@ namespace {
 // the apple touch icon for iPad.
 const int kTouchIconSize = 144;
 
-// Returns chrome::IconType the given icon_type corresponds to.
-chrome::IconType ToHistoryIconType(FaviconURL::IconType icon_type) {
+// Returns favicon_base::IconType the given icon_type corresponds to.
+favicon_base::IconType ToChromeIconType(FaviconURL::IconType icon_type) {
   switch (icon_type) {
     case FaviconURL::FAVICON:
-      return chrome::FAVICON;
+      return favicon_base::FAVICON;
     case FaviconURL::TOUCH_ICON:
-      return chrome::TOUCH_ICON;
+      return favicon_base::TOUCH_ICON;
     case FaviconURL::TOUCH_PRECOMPOSED_ICON:
-      return chrome::TOUCH_PRECOMPOSED_ICON;
+      return favicon_base::TOUCH_PRECOMPOSED_ICON;
     case FaviconURL::INVALID_ICON:
-      return chrome::INVALID_ICON;
+      return favicon_base::INVALID_ICON;
   }
   NOTREACHED();
-  return chrome::INVALID_ICON;
+  return favicon_base::INVALID_ICON;
 }
 
 // Get the maximal icon size in pixels for a icon of type |icon_type| for the
 // current platform.
-int GetMaximalIconSize(chrome::IconType icon_type) {
+int GetMaximalIconSize(favicon_base::IconType icon_type) {
   switch (icon_type) {
-    case chrome::FAVICON:
+    case favicon_base::FAVICON:
 #if defined(OS_ANDROID)
       return 192;
 #else
       return gfx::ImageSkia::GetMaxSupportedScale() * gfx::kFaviconSize;
 #endif
-    case chrome::TOUCH_ICON:
-    case chrome::TOUCH_PRECOMPOSED_ICON:
+    case favicon_base::TOUCH_ICON:
+    case favicon_base::TOUCH_PRECOMPOSED_ICON:
       return kTouchIconSize;
-    case chrome::INVALID_ICON:
+    case favicon_base::INVALID_ICON:
       return 0;
   }
   NOTREACHED();
@@ -72,9 +70,9 @@ int GetMaximalIconSize(chrome::IconType icon_type) {
 
 bool DoUrlAndIconMatch(const FaviconURL& favicon_url,
                        const GURL& url,
-                       chrome::IconType icon_type) {
+                       favicon_base::IconType icon_type) {
   return favicon_url.icon_url == url &&
-      favicon_url.icon_type == static_cast<FaviconURL::IconType>(icon_type);
+      ToChromeIconType(favicon_url.icon_type) == icon_type;
 }
 
 // Returns true if all of the icon URLs and icon types in |bitmap_results| are
@@ -82,11 +80,12 @@ bool DoUrlAndIconMatch(const FaviconURL& favicon_url,
 // Returns false if |bitmap_results| is empty.
 bool DoUrlsAndIconsMatch(
     const FaviconURL& favicon_url,
-    const std::vector<chrome::FaviconBitmapResult>& bitmap_results) {
+    const std::vector<favicon_base::FaviconBitmapResult>& bitmap_results) {
   if (bitmap_results.empty())
     return false;
 
-  chrome::IconType icon_type = ToHistoryIconType(favicon_url.icon_type);
+  const favicon_base::IconType icon_type =
+      ToChromeIconType(favicon_url.icon_type);
 
   for (size_t i = 0; i < bitmap_results.size(); ++i) {
     if (favicon_url.icon_url != bitmap_results[i].icon_url ||
@@ -108,12 +107,12 @@ bool UrlMatches(const GURL& gurl_a, const GURL& gurl_b) {
 }
 
 // Return true if |bitmap_result| is expired.
-bool IsExpired(const chrome::FaviconBitmapResult& bitmap_result) {
+bool IsExpired(const favicon_base::FaviconBitmapResult& bitmap_result) {
   return bitmap_result.expired;
 }
 
 // Return true if |bitmap_result| is valid.
-bool IsValid(const chrome::FaviconBitmapResult& bitmap_result) {
+bool IsValid(const favicon_base::FaviconBitmapResult& bitmap_result) {
   return bitmap_result.is_valid();
 }
 
@@ -122,9 +121,9 @@ bool IsValid(const chrome::FaviconBitmapResult& bitmap_result) {
 // the scale factors in FaviconUtil::GetFaviconScaleFactors().
 bool HasExpiredOrIncompleteResult(
     int desired_size_in_dip,
-    const std::vector<chrome::FaviconBitmapResult>& bitmap_results) {
+    const std::vector<favicon_base::FaviconBitmapResult>& bitmap_results) {
   // Check if at least one of the bitmaps is expired.
-  std::vector<chrome::FaviconBitmapResult>::const_iterator it =
+  std::vector<favicon_base::FaviconBitmapResult>::const_iterator it =
       std::find_if(bitmap_results.begin(), bitmap_results.end(), IsExpired);
   if (it != bitmap_results.end())
     return true;
@@ -159,10 +158,48 @@ bool HasExpiredOrIncompleteResult(
 
 // Returns true if at least one of |bitmap_results| is valid.
 bool HasValidResult(
-    const std::vector<chrome::FaviconBitmapResult>& bitmap_results) {
-  std::vector<chrome::FaviconBitmapResult>::const_iterator it =
-      std::find_if(bitmap_results.begin(), bitmap_results.end(), IsValid);
-  return it != bitmap_results.end();
+    const std::vector<favicon_base::FaviconBitmapResult>& bitmap_results) {
+  return std::find_if(bitmap_results.begin(), bitmap_results.end(), IsValid) !=
+      bitmap_results.end();
+}
+
+// Returns the index of the entry with the largest area that is not larger than
+// |max_area|; -1 if there is no such match.
+int GetLargestSizeIndex(const std::vector<gfx::Size>& sizes, int max_area) {
+  DCHECK(!sizes.empty());
+  int ret = -1;
+  for (size_t i = 0; i < sizes.size(); ++i) {
+    int area = sizes[i].GetArea();
+    if ((ret == -1 || sizes[ret].GetArea() < area) && area <= max_area)
+      ret = i;
+  }
+  return ret;
+}
+
+// Return the index of a size which is same as the given |size|, -1 returned if
+// there is no such bitmap.
+int GetIndexBySize(const std::vector<gfx::Size>& sizes,
+                   const gfx::Size& size) {
+  DCHECK(!sizes.empty());
+  std::vector<gfx::Size>::const_iterator i =
+      std::find(sizes.begin(), sizes.end(), size);
+  if (i == sizes.end())
+    return -1;
+
+  return static_cast<int>(i - sizes.begin());
+}
+
+// Compare function used for std::stable_sort to sort as descend.
+bool CompareIconSize(const FaviconURL& b1, const FaviconURL& b2) {
+  int area1 = 0;
+  if (!b1.icon_sizes.empty())
+    area1 = b1.icon_sizes.front().GetArea();
+
+  int area2 = 0;
+  if (!b2.icon_sizes.empty())
+    area2 = b2.icon_sizes.front().GetArea();
+
+  return area1 > area2;
 }
 
 }  // namespace
@@ -170,8 +207,7 @@ bool HasValidResult(
 ////////////////////////////////////////////////////////////////////////////////
 
 FaviconHandler::DownloadRequest::DownloadRequest()
-    : icon_type(chrome::INVALID_ICON) {
-}
+    : icon_type(favicon_base::INVALID_ICON) {}
 
 FaviconHandler::DownloadRequest::~DownloadRequest() {
 }
@@ -179,18 +215,13 @@ FaviconHandler::DownloadRequest::~DownloadRequest() {
 FaviconHandler::DownloadRequest::DownloadRequest(
     const GURL& url,
     const GURL& image_url,
-    chrome::IconType icon_type)
-    : url(url),
-      image_url(image_url),
-      icon_type(icon_type) {
-}
+    favicon_base::IconType icon_type)
+    : url(url), image_url(image_url), icon_type(icon_type) {}
 
 ////////////////////////////////////////////////////////////////////////////////
 
 FaviconHandler::FaviconCandidate::FaviconCandidate()
-    : score(0),
-      icon_type(chrome::INVALID_ICON) {
-}
+    : score(0), icon_type(favicon_base::INVALID_ICON) {}
 
 FaviconHandler::FaviconCandidate::~FaviconCandidate() {
 }
@@ -200,27 +231,29 @@ FaviconHandler::FaviconCandidate::FaviconCandidate(
     const GURL& image_url,
     const gfx::Image& image,
     float score,
-    chrome::IconType icon_type)
+    favicon_base::IconType icon_type)
     : url(url),
       image_url(image_url),
       image(image),
       score(score),
-      icon_type(icon_type) {
-}
+      icon_type(icon_type) {}
 
 ////////////////////////////////////////////////////////////////////////////////
 
-FaviconHandler::FaviconHandler(Profile* profile,
-                               FaviconHandlerDelegate* delegate,
-                               Type icon_type)
+FaviconHandler::FaviconHandler(FaviconClient* client,
+                               FaviconDriver* driver,
+                               Type icon_type,
+                               bool download_largest_icon)
     : got_favicon_from_history_(false),
       favicon_expired_or_incomplete_(false),
-      icon_types_(icon_type == FAVICON ? chrome::FAVICON :
-          chrome::TOUCH_ICON | chrome::TOUCH_PRECOMPOSED_ICON),
-      profile_(profile),
-      delegate_(delegate) {
-  DCHECK(profile_);
-  DCHECK(delegate_);
+      icon_types_(icon_type == FAVICON
+                      ? favicon_base::FAVICON
+                      : favicon_base::TOUCH_ICON |
+                            favicon_base::TOUCH_PRECOMPOSED_ICON),
+      download_largest_icon_(download_largest_icon),
+      client_(client),
+      driver_(driver) {
+  DCHECK(driver_);
 }
 
 FaviconHandler::~FaviconHandler() {
@@ -237,69 +270,74 @@ void FaviconHandler::FetchFavicon(const GURL& url) {
   // Request the favicon from the history service. In parallel to this the
   // renderer is going to notify us (well WebContents) when the favicon url is
   // available.
-  if (GetFaviconService()) {
-    GetFaviconForURL(
+  if (client_->GetFaviconService()) {
+    GetFaviconForURLFromFaviconService(
         url_,
         icon_types_,
-        base::Bind(&FaviconHandler::OnFaviconDataForInitialURL,
-                   base::Unretained(this)),
+        base::Bind(
+            &FaviconHandler::OnFaviconDataForInitialURLFromFaviconService,
+            base::Unretained(this)),
         &cancelable_task_tracker_);
   }
 }
 
-FaviconService* FaviconHandler::GetFaviconService() {
-  return FaviconServiceFactory::GetForProfile(
-      profile_, Profile::EXPLICIT_ACCESS);
-}
-
 bool FaviconHandler::UpdateFaviconCandidate(const GURL& url,
                                             const GURL& image_url,
                                             const gfx::Image& image,
                                             float score,
-                                            chrome::IconType icon_type) {
-  bool update_candidate = false;
-  bool exact_match = score == 1;
-  if (preferred_icon_size() == 0) {
-    // No preferred size, use this icon.
-    update_candidate = true;
-    exact_match = true;
-  } else if (favicon_candidate_.icon_type == chrome::INVALID_ICON) {
-    // No current candidate, use this.
-    update_candidate = true;
+                                            favicon_base::IconType icon_type) {
+  bool replace_best_favicon_candidate = false;
+  bool exact_match = false;
+  if (download_largest_icon_) {
+    replace_best_favicon_candidate =
+        image.Size().GetArea() >
+        best_favicon_candidate_.image.Size().GetArea();
+
+    gfx::Size largest = best_favicon_candidate_.image.Size();
+    if (replace_best_favicon_candidate)
+      largest = image.Size();
+
+    // exact match (stop downloading next icon) only if
+    // - current candidate is only candidate.
+    // - next candidate doesn't have sizes attributes, in this case, the rest
+    //   candidates don't have sizes attribute either, stop downloading now,
+    //   otherwise, all favicon without sizes attribute are downloaded.
+    // - next candidate has sizes attribute and it is not larger than largest.
+    exact_match = image_urls_.size() == 1 ||
+        image_urls_[1].icon_sizes.empty() ||
+        image_urls_[1].icon_sizes[0].GetArea() < largest.GetArea();
   } else {
-    if (exact_match) {
-      // Exact match, use this.
-      update_candidate = true;
-    } else {
-      // Compare against current candidate.
-      if (score > favicon_candidate_.score)
-        update_candidate = true;
-    }
+    exact_match = score == 1 || preferred_icon_size() == 0;
+    replace_best_favicon_candidate =
+        exact_match ||
+        best_favicon_candidate_.icon_type == favicon_base::INVALID_ICON ||
+        score > best_favicon_candidate_.score;
   }
-  if (update_candidate) {
-    favicon_candidate_ = FaviconCandidate(
+  if (replace_best_favicon_candidate) {
+    best_favicon_candidate_ = FaviconCandidate(
         url, image_url, image, score, icon_type);
   }
   return exact_match;
 }
 
-void FaviconHandler::SetFavicon(
-    const GURL& url,
-    const GURL& icon_url,
-    const gfx::Image& image,
-    chrome::IconType icon_type) {
-  if (GetFaviconService() && ShouldSaveFavicon(url))
+void FaviconHandler::SetFavicon(const GURL& url,
+                                const GURL& icon_url,
+                                const gfx::Image& image,
+                                favicon_base::IconType icon_type) {
+  if (client_->GetFaviconService() && ShouldSaveFavicon(url))
     SetHistoryFavicons(url, icon_url, icon_type, image);
 
-  if (UrlMatches(url, url_) && icon_type == chrome::FAVICON) {
+  if (UrlMatches(url, url_) && icon_type == favicon_base::FAVICON) {
     NavigationEntry* entry = GetEntry();
     if (entry)
-      UpdateFavicon(entry, icon_url, image);
+      SetFaviconOnNavigationEntry(entry, icon_url, image);
   }
 }
 
-void FaviconHandler::UpdateFavicon(NavigationEntry* entry,
-    const std::vector<chrome::FaviconBitmapResult>& favicon_bitmap_results) {
+void FaviconHandler::SetFaviconOnNavigationEntry(
+    NavigationEntry* entry,
+    const std::vector<favicon_base::FaviconBitmapResult>&
+        favicon_bitmap_results) {
   gfx::Image resized_image = FaviconUtil::SelectFaviconFramesFromPNGs(
       favicon_bitmap_results,
       FaviconUtil::GetFaviconScaleFactors(),
@@ -308,12 +346,13 @@ void FaviconHandler::UpdateFavicon(NavigationEntry* entry,
   // not matter which result we get the |icon_url| from.
   const GURL icon_url = favicon_bitmap_results.empty() ?
       GURL() : favicon_bitmap_results[0].icon_url;
-  UpdateFavicon(entry, icon_url, resized_image);
+  SetFaviconOnNavigationEntry(entry, icon_url, resized_image);
 }
 
-void FaviconHandler::UpdateFavicon(NavigationEntry* entry,
-                                   const GURL& icon_url,
-                                   const gfx::Image& image) {
+void FaviconHandler::SetFaviconOnNavigationEntry(
+    NavigationEntry* entry,
+    const GURL& icon_url,
+    const gfx::Image& image) {
   // No matter what happens, we need to mark the favicon as being set.
   entry->GetFavicon().valid = true;
 
@@ -331,11 +370,9 @@ void FaviconHandler::UpdateFavicon(NavigationEntry* entry,
 }
 
 void FaviconHandler::OnUpdateFaviconURL(
-    int32 page_id,
     const std::vector<FaviconURL>& candidates) {
-
   image_urls_.clear();
-  favicon_candidate_ = FaviconCandidate();
+  best_favicon_candidate_ = FaviconCandidate();
   for (std::vector<FaviconURL>::const_iterator i = candidates.begin();
        i != candidates.end(); ++i) {
     if (!i->icon_url.is_empty() && (i->icon_type & icon_types_))
@@ -347,9 +384,12 @@ void FaviconHandler::OnUpdateFaviconURL(
   if (image_urls_.empty())
     return;
 
-  if (!GetFaviconService())
+  if (!client_->GetFaviconService())
     return;
 
+  if (download_largest_icon_)
+    SortAndPruneImageUrls();
+
   ProcessCurrentUrl();
 }
 
@@ -357,14 +397,17 @@ void FaviconHandler::ProcessCurrentUrl() {
   DCHECK(!image_urls_.empty());
 
   NavigationEntry* entry = GetEntry();
-  if (!entry)
+
+  // current_candidate() may return NULL if download_largest_icon_ is true and
+  // all the sizes are larger than the max.
+  if (!entry || !current_candidate())
     return;
 
-  // For FAVICON.
   if (current_candidate()->icon_type == FaviconURL::FAVICON) {
     if (!favicon_expired_or_incomplete_ && entry->GetFavicon().valid &&
-        DoUrlAndIconMatch(*current_candidate(), entry->GetFavicon().url,
-                          chrome::FAVICON))
+        DoUrlAndIconMatch(*current_candidate(),
+                          entry->GetFavicon().url,
+                          favicon_base::FAVICON))
       return;
   } else if (!favicon_expired_or_incomplete_ && got_favicon_from_history_ &&
              HasValidResult(history_results_) &&
@@ -373,8 +416,9 @@ void FaviconHandler::ProcessCurrentUrl() {
   }
 
   if (got_favicon_from_history_)
-    DownloadFaviconOrAskHistory(entry->GetURL(), current_candidate()->icon_url,
-        ToHistoryIconType(current_candidate()->icon_type));
+    DownloadFaviconOrAskFaviconService(
+        entry->GetURL(), current_candidate()->icon_url,
+        ToChromeIconType(current_candidate()->icon_type));
 }
 
 void FaviconHandler::OnDidDownloadFavicon(
@@ -391,42 +435,66 @@ void FaviconHandler::OnDidDownloadFavicon(
 
   if (current_candidate() &&
       DoUrlAndIconMatch(*current_candidate(), image_url, i->second.icon_type)) {
-    float score = 0.0f;
-    std::vector<ui::ScaleFactor> scale_factors =
-        FaviconUtil::GetFaviconScaleFactors();
-    gfx::Image image(SelectFaviconFrames(bitmaps,
-                                         original_bitmap_sizes,
-                                         scale_factors,
-                                         preferred_icon_size(),
-                                         &score));
-
-    // The downloaded icon is still valid when there is no FaviconURL update
-    // during the downloading.
     bool request_next_icon = true;
-    if (!bitmaps.empty()) {
-      request_next_icon = !UpdateFaviconCandidate(
-          i->second.url, image_url, image, score, i->second.icon_type);
+    float score = 0.0f;
+    gfx::ImageSkia image_skia;
+    if (download_largest_icon_ && !bitmaps.empty()) {
+      int index = -1;
+      int max_size = GetMaximalIconSize(i->second.icon_type);
+      // Use the largest bitmap if FaviconURL doesn't have sizes attribute.
+      if (current_candidate()->icon_sizes.empty()) {
+        index = GetLargestSizeIndex(original_bitmap_sizes, max_size * max_size);
+      } else {
+        index = GetIndexBySize(original_bitmap_sizes,
+                               current_candidate()->icon_sizes[0]);
+        // Find largest bitmap if there is no one exactly matched.
+        if (index == -1) {
+          index = GetLargestSizeIndex(original_bitmap_sizes,
+                                      max_size * max_size);
+        }
+      }
+      if (index != -1)
+        image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1));
+    } else {
+      std::vector<ui::ScaleFactor> scale_factors =
+          FaviconUtil::GetFaviconScaleFactors();
+      image_skia = SelectFaviconFrames(bitmaps,
+                                       original_bitmap_sizes,
+                                       scale_factors,
+                                       preferred_icon_size(),
+                                       &score);
+    }
+
+    if (!image_skia.isNull()) {
+      gfx::Image image(image_skia);
+      // The downloaded icon is still valid when there is no FaviconURL update
+      // during the downloading.
+      if (!bitmaps.empty()) {
+        request_next_icon = !UpdateFaviconCandidate(
+            i->second.url, image_url, image, score, i->second.icon_type);
+      }
     }
     if (request_next_icon && GetEntry() && image_urls_.size() > 1) {
       // Remove the first member of image_urls_ and process the remaining.
-      image_urls_.pop_front();
+      image_urls_.erase(image_urls_.begin());
       ProcessCurrentUrl();
-    } else if (favicon_candidate_.icon_type != chrome::INVALID_ICON) {
+    } else if (best_favicon_candidate_.icon_type !=
+               favicon_base::INVALID_ICON) {
       // No more icons to request, set the favicon from the candidate.
-      SetFavicon(favicon_candidate_.url,
-                 favicon_candidate_.image_url,
-                 favicon_candidate_.image,
-                 favicon_candidate_.icon_type);
+      SetFavicon(best_favicon_candidate_.url,
+                 best_favicon_candidate_.image_url,
+                 best_favicon_candidate_.image,
+                 best_favicon_candidate_.icon_type);
       // Reset candidate.
       image_urls_.clear();
-      favicon_candidate_ = FaviconCandidate();
+      best_favicon_candidate_ = FaviconCandidate();
     }
   }
   download_requests_.erase(i);
 }
 
 NavigationEntry* FaviconHandler::GetEntry() {
-  NavigationEntry* entry = delegate_->GetActiveEntry();
+  NavigationEntry* entry = driver_->GetActiveEntry();
   if (entry && UrlMatches(entry->GetURL(), url_))
     return entry;
 
@@ -441,67 +509,67 @@ int FaviconHandler::DownloadFavicon(const GURL& image_url,
     NOTREACHED();
     return 0;
   }
-  return delegate_->StartDownload(image_url, max_bitmap_size);
+  return driver_->StartDownload(image_url, max_bitmap_size);
 }
 
 void FaviconHandler::UpdateFaviconMappingAndFetch(
     const GURL& page_url,
     const GURL& icon_url,
-    chrome::IconType icon_type,
+    favicon_base::IconType icon_type,
     const FaviconService::FaviconResultsCallback& callback,
     base::CancelableTaskTracker* tracker) {
   // TODO(pkotwicz): pass in all of |image_urls_| to
   // UpdateFaviconMappingsAndFetch().
   std::vector<GURL> icon_urls;
   icon_urls.push_back(icon_url);
-  GetFaviconService()->UpdateFaviconMappingsAndFetch(
+  client_->GetFaviconService()->UpdateFaviconMappingsAndFetch(
       page_url, icon_urls, icon_type, preferred_icon_size(), callback, tracker);
 }
 
-void FaviconHandler::GetFavicon(
+void FaviconHandler::GetFaviconFromFaviconService(
     const GURL& icon_url,
-    chrome::IconType icon_type,
+    favicon_base::IconType icon_type,
     const FaviconService::FaviconResultsCallback& callback,
     base::CancelableTaskTracker* tracker) {
-  GetFaviconService()->GetFavicon(
+  client_->GetFaviconService()->GetFavicon(
       icon_url, icon_type, preferred_icon_size(), callback, tracker);
 }
 
-void FaviconHandler::GetFaviconForURL(
+void FaviconHandler::GetFaviconForURLFromFaviconService(
     const GURL& page_url,
     int icon_types,
     const FaviconService::FaviconResultsCallback& callback,
     base::CancelableTaskTracker* tracker) {
-  GetFaviconService()->GetFaviconForURL(
-      FaviconService::FaviconForURLParams(page_url, icon_types,
-                                          preferred_icon_size()),
+  client_->GetFaviconService()->GetFaviconForURL(
+      FaviconService::FaviconForURLParams(
+          page_url, icon_types, preferred_icon_size()),
       callback,
       tracker);
 }
 
 void FaviconHandler::SetHistoryFavicons(const GURL& page_url,
                                         const GURL& icon_url,
-                                        chrome::IconType icon_type,
+                                        favicon_base::IconType icon_type,
                                         const gfx::Image& image) {
-  GetFaviconService()->SetFavicons(page_url, icon_url, icon_type, image);
+  client_->GetFaviconService()->SetFavicons(
+      page_url, icon_url, icon_type, image);
 }
 
 bool FaviconHandler::ShouldSaveFavicon(const GURL& url) {
-  if (!profile_->IsOffTheRecord())
+  if (!driver_->IsOffTheRecord())
     return true;
 
   // Otherwise store the favicon if the page is bookmarked.
-  BookmarkService* bookmark_service =
-      BookmarkService::FromBrowserContext(profile_);
-  return bookmark_service && bookmark_service->IsBookmarked(url);
+  return client_->IsBookmarked(url);
 }
 
 void FaviconHandler::NotifyFaviconUpdated(bool icon_url_changed) {
-  delegate_->NotifyFaviconUpdated(icon_url_changed);
+  driver_->NotifyFaviconUpdated(icon_url_changed);
 }
 
-void FaviconHandler::OnFaviconDataForInitialURL(
-    const std::vector<chrome::FaviconBitmapResult>& favicon_bitmap_results) {
+void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService(
+    const std::vector<favicon_base::FaviconBitmapResult>&
+        favicon_bitmap_results) {
   NavigationEntry* entry = GetEntry();
   if (!entry)
     return;
@@ -513,7 +581,7 @@ void FaviconHandler::OnFaviconDataForInitialURL(
   favicon_expired_or_incomplete_ = has_results && HasExpiredOrIncompleteResult(
       preferred_icon_size(), favicon_bitmap_results);
 
-  if (has_results && icon_types_ == chrome::FAVICON &&
+  if (has_results && icon_types_ == favicon_base::FAVICON &&
       !entry->GetFavicon().valid &&
       (!current_candidate() ||
        DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) {
@@ -522,7 +590,7 @@ void FaviconHandler::OnFaviconDataForInitialURL(
       // doesn't have an icon. Set the favicon now, and if the favicon turns out
       // to be expired (or the wrong url) we'll fetch later on. This way the
       // user doesn't see a flash of the default favicon.
-      UpdateFavicon(entry, favicon_bitmap_results);
+      SetFaviconOnNavigationEntry(entry, favicon_bitmap_results);
     } else {
       // If |favicon_bitmap_results| does not have any valid results, treat the
       // favicon as if it's expired.
@@ -537,34 +605,35 @@ void FaviconHandler::OnFaviconDataForInitialURL(
       // Mapping in the database is wrong. DownloadFavIconOrAskHistory will
       // update the mapping for this url and download the favicon if we don't
       // already have it.
-      DownloadFaviconOrAskHistory(entry->GetURL(),
-          current_candidate()->icon_url,
-          static_cast<chrome::IconType>(current_candidate()->icon_type));
+      DownloadFaviconOrAskFaviconService(
+          entry->GetURL(), current_candidate()->icon_url,
+          ToChromeIconType(current_candidate()->icon_type));
     }
   } else if (current_candidate()) {
-    // We know the official url for the favicon, by either don't have the
-    // favicon or its expired. Continue on to DownloadFaviconOrAskHistory to
+    // We know the official url for the favicon, but either don't have the
+    // favicon or it's expired. Continue on to DownloadFaviconOrAskHistory to
     // either download or check history again.
-    DownloadFaviconOrAskHistory(entry->GetURL(), current_candidate()->icon_url,
-        ToHistoryIconType(current_candidate()->icon_type));
+    DownloadFaviconOrAskFaviconService(
+        entry->GetURL(), current_candidate()->icon_url,
+        ToChromeIconType(current_candidate()->icon_type));
   }
   // else we haven't got the icon url. When we get it we'll ask the
   // renderer to download the icon.
 }
 
-void FaviconHandler::DownloadFaviconOrAskHistory(
+void FaviconHandler::DownloadFaviconOrAskFaviconService(
     const GURL& page_url,
     const GURL& icon_url,
-    chrome::IconType icon_type) {
+    favicon_base::IconType icon_type) {
   if (favicon_expired_or_incomplete_) {
     // We have the mapping, but the favicon is out of date. Download it now.
     ScheduleDownload(page_url, icon_url, icon_type);
-  } else if (GetFaviconService()) {
+  } else if (client_->GetFaviconService()) {
     // We don't know the favicon, but we may have previously downloaded the
     // favicon for another page that shares the same favicon. Ask for the
     // favicon given the favicon URL.
-    if (profile_->IsOffTheRecord()) {
-      GetFavicon(
+    if (driver_->IsOffTheRecord()) {
+      GetFaviconFromFaviconService(
           icon_url, icon_type,
           base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)),
           &cancelable_task_tracker_);
@@ -574,7 +643,6 @@ void FaviconHandler::DownloadFaviconOrAskHistory(
       // 2. If the favicon exists in the database, this updates the database to
       //    include the mapping between the page url and the favicon url.
       // This is asynchronous. The history service will call back when done.
-      // Issue the request and associate the current page ID with it.
       UpdateFaviconMappingAndFetch(
           page_url, icon_url, icon_type,
           base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)),
@@ -583,8 +651,8 @@ void FaviconHandler::DownloadFaviconOrAskHistory(
   }
 }
 
-void FaviconHandler::OnFaviconData(
-    const std::vector<chrome::FaviconBitmapResult>& favicon_bitmap_results) {
+void FaviconHandler::OnFaviconData(const std::vector<
+    favicon_base::FaviconBitmapResult>& favicon_bitmap_results) {
   NavigationEntry* entry = GetEntry();
   if (!entry)
     return;
@@ -593,17 +661,17 @@ void FaviconHandler::OnFaviconData(
   bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult(
       preferred_icon_size(), favicon_bitmap_results);
 
-  if (has_results && icon_types_ == chrome::FAVICON) {
+  if (has_results && icon_types_ == favicon_base::FAVICON) {
     if (HasValidResult(favicon_bitmap_results)) {
       // There is a favicon, set it now. If expired we'll download the current
       // one again, but at least the user will get some icon instead of the
       // default and most likely the current one is fine anyway.
-      UpdateFavicon(entry, favicon_bitmap_results);
+      SetFaviconOnNavigationEntry(entry, favicon_bitmap_results);
     }
     if (has_expired_or_incomplete_result) {
       // The favicon is out of date. Request the current one.
-      ScheduleDownload(entry->GetURL(), entry->GetFavicon().url,
-                       chrome::FAVICON);
+      ScheduleDownload(
+          entry->GetURL(), entry->GetFavicon().url, favicon_base::FAVICON);
     }
   } else if (current_candidate() &&
       (!has_results || has_expired_or_incomplete_result ||
@@ -611,20 +679,19 @@ void FaviconHandler::OnFaviconData(
     // We don't know the favicon, it is out of date or its type is not same as
     // one got from page. Request the current one.
     ScheduleDownload(entry->GetURL(), current_candidate()->icon_url,
-        ToHistoryIconType(current_candidate()->icon_type));
+                     ToChromeIconType(current_candidate()->icon_type));
   }
   history_results_ = favicon_bitmap_results;
 }
 
-int FaviconHandler::ScheduleDownload(
-    const GURL& url,
-    const GURL& image_url,
-    chrome::IconType icon_type) {
+int FaviconHandler::ScheduleDownload(const GURL& url,
+                                     const GURL& image_url,
+                                     favicon_base::IconType icon_type) {
   // A max bitmap size is specified to avoid receiving huge bitmaps in
-  // OnDidDownloadFavicon(). See FaviconHandlerDelegate::StartDownload()
+  // OnDidDownloadFavicon(). See FaviconDriver::StartDownload()
   // for more details about the max bitmap size.
   const int download_id = DownloadFavicon(image_url,
-      GetMaximalIconSize(icon_type));
+                                          GetMaximalIconSize(icon_type));
   if (download_id) {
     // Download ids should be unique.
     DCHECK(download_requests_.find(download_id) == download_requests_.end());
@@ -634,3 +701,25 @@ int FaviconHandler::ScheduleDownload(
 
   return download_id;
 }
+
+void FaviconHandler::SortAndPruneImageUrls() {
+  for (std::vector<FaviconURL>::iterator i = image_urls_.begin();
+       i != image_urls_.end();) {
+    if (i->icon_sizes.empty()) {
+      ++i;
+      continue;
+    }
+    int max_size = GetMaximalIconSize(ToChromeIconType(i->icon_type));
+    int index = GetLargestSizeIndex(i->icon_sizes, max_size * max_size);
+    if (index == -1) {
+      i = image_urls_.erase(i);
+    } else {
+      gfx::Size largest = i->icon_sizes[index];
+      i->icon_sizes.clear();
+      i->icon_sizes.push_back(largest);
+      ++i;
+    }
+  }
+  std::stable_sort(image_urls_.begin(), image_urls_.end(),
+                   CompareIconSize);
+}