| OLD | NEW | 
|    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |    1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "components/favicon/core/favicon_service.h" |    5 #include "components/favicon/core/favicon_service.h" | 
|    6  |    6  | 
|    7 #include <stddef.h> |  | 
|    8 #include <cmath> |  | 
|    9 #include <utility> |  | 
|   10  |  | 
|   11 #include "base/hash.h" |  | 
|   12 #include "base/single_thread_task_runner.h" |  | 
|   13 #include "base/threading/thread_task_runner_handle.h" |  | 
|   14 #include "base/trace_event/trace_event.h" |  | 
|   15 #include "components/favicon/core/favicon_client.h" |  | 
|   16 #include "components/favicon_base/favicon_util.h" |  | 
|   17 #include "components/favicon_base/select_favicon_frames.h" |  | 
|   18 #include "components/history/core/browser/history_service.h" |  | 
|   19 #include "third_party/skia/include/core/SkBitmap.h" |  | 
|   20 #include "ui/gfx/codec/png_codec.h" |  | 
|   21 #include "ui/gfx/favicon_size.h" |  | 
|   22 #include "ui/gfx/image/image_skia.h" |  | 
|   23 #include "url/gurl.h" |  | 
|   24  |  | 
|   25 namespace favicon { |    7 namespace favicon { | 
|   26 namespace { |  | 
|   27  |  | 
|   28 // Helper to run callback with empty results if we cannot get the history |  | 
|   29 // service. |  | 
|   30 base::CancelableTaskTracker::TaskId RunWithEmptyResultAsync( |  | 
|   31     const favicon_base::FaviconResultsCallback& callback, |  | 
|   32     base::CancelableTaskTracker* tracker) { |  | 
|   33   scoped_refptr<base::SingleThreadTaskRunner> thread_runner( |  | 
|   34       base::ThreadTaskRunnerHandle::Get()); |  | 
|   35   return tracker->PostTask( |  | 
|   36       thread_runner.get(), FROM_HERE, |  | 
|   37       base::Bind(callback, |  | 
|   38                  std::vector<favicon_base::FaviconRawBitmapResult>())); |  | 
|   39 } |  | 
|   40  |  | 
|   41 // Returns a vector of pixel edge sizes from |size_in_dip| and |  | 
|   42 // favicon_base::GetFaviconScales(). |  | 
|   43 std::vector<int> GetPixelSizesForFaviconScales(int size_in_dip) { |  | 
|   44   std::vector<float> scales = favicon_base::GetFaviconScales(); |  | 
|   45   std::vector<int> sizes_in_pixel; |  | 
|   46   for (size_t i = 0; i < scales.size(); ++i) { |  | 
|   47     sizes_in_pixel.push_back(std::ceil(size_in_dip * scales[i])); |  | 
|   48   } |  | 
|   49   return sizes_in_pixel; |  | 
|   50 } |  | 
|   51  |  | 
|   52 }  // namespace |  | 
|   53  |  | 
|   54 FaviconService::FaviconService(std::unique_ptr<FaviconClient> favicon_client, |  | 
|   55                                history::HistoryService* history_service) |  | 
|   56     : favicon_client_(std::move(favicon_client)), |  | 
|   57       history_service_(history_service) {} |  | 
|   58  |  | 
|   59 FaviconService::~FaviconService() { |  | 
|   60 } |  | 
|   61  |    8  | 
|   62 // static |    9 // static | 
|   63 void FaviconService::FaviconResultsCallbackRunner( |   10 void FaviconService::FaviconResultsCallbackRunner( | 
|   64     const favicon_base::FaviconResultsCallback& callback, |   11     const favicon_base::FaviconResultsCallback& callback, | 
|   65     const std::vector<favicon_base::FaviconRawBitmapResult>* results) { |   12     const std::vector<favicon_base::FaviconRawBitmapResult>* results) { | 
|   66   callback.Run(*results); |   13   callback.Run(*results); | 
|   67 } |   14 } | 
|   68  |   15  | 
|   69 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImage( |  | 
|   70     const GURL& icon_url, |  | 
|   71     const favicon_base::FaviconImageCallback& callback, |  | 
|   72     base::CancelableTaskTracker* tracker) { |  | 
|   73   TRACE_EVENT0("browser", "FaviconService::GetFaviconImage"); |  | 
|   74   favicon_base::FaviconResultsCallback callback_runner = |  | 
|   75       base::Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults, |  | 
|   76                  base::Unretained(this), callback, gfx::kFaviconSize); |  | 
|   77   if (history_service_) { |  | 
|   78     std::vector<GURL> icon_urls; |  | 
|   79     icon_urls.push_back(icon_url); |  | 
|   80     return history_service_->GetFavicons( |  | 
|   81         icon_urls, |  | 
|   82         favicon_base::FAVICON, |  | 
|   83         GetPixelSizesForFaviconScales(gfx::kFaviconSize), |  | 
|   84         callback_runner, |  | 
|   85         tracker); |  | 
|   86   } |  | 
|   87   return RunWithEmptyResultAsync(callback_runner, tracker); |  | 
|   88 } |  | 
|   89  |  | 
|   90 base::CancelableTaskTracker::TaskId FaviconService::GetRawFavicon( |  | 
|   91     const GURL& icon_url, |  | 
|   92     favicon_base::IconType icon_type, |  | 
|   93     int desired_size_in_pixel, |  | 
|   94     const favicon_base::FaviconRawBitmapCallback& callback, |  | 
|   95     base::CancelableTaskTracker* tracker) { |  | 
|   96   TRACE_EVENT0("browser", "FaviconService::GetRawFavicon"); |  | 
|   97   favicon_base::FaviconResultsCallback callback_runner = |  | 
|   98       base::Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults, |  | 
|   99                  base::Unretained(this), callback, desired_size_in_pixel); |  | 
|  100  |  | 
|  101   if (history_service_) { |  | 
|  102     std::vector<GURL> icon_urls; |  | 
|  103     icon_urls.push_back(icon_url); |  | 
|  104     std::vector<int> desired_sizes_in_pixel; |  | 
|  105     desired_sizes_in_pixel.push_back(desired_size_in_pixel); |  | 
|  106  |  | 
|  107     return history_service_->GetFavicons( |  | 
|  108         icon_urls, icon_type, desired_sizes_in_pixel, callback_runner, tracker); |  | 
|  109   } |  | 
|  110   return RunWithEmptyResultAsync(callback_runner, tracker); |  | 
|  111 } |  | 
|  112  |  | 
|  113 base::CancelableTaskTracker::TaskId FaviconService::GetFavicon( |  | 
|  114     const GURL& icon_url, |  | 
|  115     favicon_base::IconType icon_type, |  | 
|  116     int desired_size_in_dip, |  | 
|  117     const favicon_base::FaviconResultsCallback& callback, |  | 
|  118     base::CancelableTaskTracker* tracker) { |  | 
|  119   TRACE_EVENT0("browser", "FaviconService::GetFavicon"); |  | 
|  120   if (history_service_) { |  | 
|  121     std::vector<GURL> icon_urls; |  | 
|  122     icon_urls.push_back(icon_url); |  | 
|  123     return history_service_->GetFavicons( |  | 
|  124         icon_urls, |  | 
|  125         icon_type, |  | 
|  126         GetPixelSizesForFaviconScales(desired_size_in_dip), |  | 
|  127         callback, |  | 
|  128         tracker); |  | 
|  129   } |  | 
|  130   return RunWithEmptyResultAsync(callback, tracker); |  | 
|  131 } |  | 
|  132  |  | 
|  133 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImageForPageURL( |  | 
|  134     const GURL& page_url, |  | 
|  135     const favicon_base::FaviconImageCallback& callback, |  | 
|  136     base::CancelableTaskTracker* tracker) { |  | 
|  137   TRACE_EVENT0("browser", "FaviconService::GetFaviconImageForPageURL"); |  | 
|  138   return GetFaviconForPageURLImpl( |  | 
|  139       page_url, favicon_base::FAVICON, |  | 
|  140       GetPixelSizesForFaviconScales(gfx::kFaviconSize), |  | 
|  141       base::Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults, |  | 
|  142                  base::Unretained(this), callback, gfx::kFaviconSize), |  | 
|  143       tracker); |  | 
|  144 } |  | 
|  145  |  | 
|  146 base::CancelableTaskTracker::TaskId FaviconService::GetRawFaviconForPageURL( |  | 
|  147     const GURL& page_url, |  | 
|  148     int icon_types, |  | 
|  149     int desired_size_in_pixel, |  | 
|  150     const favicon_base::FaviconRawBitmapCallback& callback, |  | 
|  151     base::CancelableTaskTracker* tracker) { |  | 
|  152   TRACE_EVENT0("browser", "FaviconService::GetRawFaviconForPageURL"); |  | 
|  153   std::vector<int> desired_sizes_in_pixel; |  | 
|  154   desired_sizes_in_pixel.push_back(desired_size_in_pixel); |  | 
|  155   return GetFaviconForPageURLImpl( |  | 
|  156       page_url, icon_types, desired_sizes_in_pixel, |  | 
|  157       base::Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults, |  | 
|  158                  base::Unretained(this), callback, desired_size_in_pixel), |  | 
|  159       tracker); |  | 
|  160 } |  | 
|  161  |  | 
|  162 base::CancelableTaskTracker::TaskId |  | 
|  163 FaviconService::GetLargestRawFaviconForPageURL( |  | 
|  164     const GURL& page_url, |  | 
|  165     const std::vector<int>& icon_types, |  | 
|  166     int minimum_size_in_pixels, |  | 
|  167     const favicon_base::FaviconRawBitmapCallback& callback, |  | 
|  168     base::CancelableTaskTracker* tracker) { |  | 
|  169   TRACE_EVENT0("browser", "FaviconService::GetLargestRawFaviconForPageURL"); |  | 
|  170   favicon_base::FaviconResultsCallback favicon_results_callback = |  | 
|  171       base::Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults, |  | 
|  172                  base::Unretained(this), callback, 0); |  | 
|  173   if (favicon_client_ && favicon_client_->IsNativeApplicationURL(page_url)) { |  | 
|  174     std::vector<int> desired_sizes_in_pixel; |  | 
|  175     desired_sizes_in_pixel.push_back(0); |  | 
|  176     return favicon_client_->GetFaviconForNativeApplicationURL( |  | 
|  177         page_url, desired_sizes_in_pixel, favicon_results_callback, tracker); |  | 
|  178   } |  | 
|  179   if (history_service_) { |  | 
|  180     return history_service_->GetLargestFaviconForURL(page_url, icon_types, |  | 
|  181         minimum_size_in_pixels, callback, tracker); |  | 
|  182   } |  | 
|  183   return RunWithEmptyResultAsync(favicon_results_callback, tracker); |  | 
|  184 } |  | 
|  185  |  | 
|  186 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURL( |  | 
|  187     const GURL& page_url, |  | 
|  188     int icon_types, |  | 
|  189     int desired_size_in_dip, |  | 
|  190     const favicon_base::FaviconResultsCallback& callback, |  | 
|  191     base::CancelableTaskTracker* tracker) { |  | 
|  192   TRACE_EVENT0("browser", "FaviconService::GetFaviconForPageURL"); |  | 
|  193   return GetFaviconForPageURLImpl( |  | 
|  194       page_url, |  | 
|  195       icon_types, |  | 
|  196       GetPixelSizesForFaviconScales(desired_size_in_dip), |  | 
|  197       callback, |  | 
|  198       tracker); |  | 
|  199 } |  | 
|  200  |  | 
|  201 base::CancelableTaskTracker::TaskId |  | 
|  202 FaviconService::UpdateFaviconMappingsAndFetch( |  | 
|  203     const GURL& page_url, |  | 
|  204     const std::vector<GURL>& icon_urls, |  | 
|  205     int icon_types, |  | 
|  206     int desired_size_in_dip, |  | 
|  207     const favicon_base::FaviconResultsCallback& callback, |  | 
|  208     base::CancelableTaskTracker* tracker) { |  | 
|  209   if (history_service_) { |  | 
|  210     return history_service_->UpdateFaviconMappingsAndFetch( |  | 
|  211         page_url, |  | 
|  212         icon_urls, |  | 
|  213         icon_types, |  | 
|  214         GetPixelSizesForFaviconScales(desired_size_in_dip), |  | 
|  215         callback, |  | 
|  216         tracker); |  | 
|  217   } |  | 
|  218   return RunWithEmptyResultAsync(callback, tracker); |  | 
|  219 } |  | 
|  220  |  | 
|  221 base::CancelableTaskTracker::TaskId FaviconService::GetLargestRawFaviconForID( |  | 
|  222     favicon_base::FaviconID favicon_id, |  | 
|  223     const favicon_base::FaviconRawBitmapCallback& callback, |  | 
|  224     base::CancelableTaskTracker* tracker) { |  | 
|  225   TRACE_EVENT0("browser", "FaviconService::GetLargestRawFaviconForID"); |  | 
|  226   // Use 0 as |desired_size| to get the largest bitmap for |favicon_id| without |  | 
|  227   // any resizing. |  | 
|  228   int desired_size = 0; |  | 
|  229   favicon_base::FaviconResultsCallback callback_runner = |  | 
|  230       base::Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults, |  | 
|  231                  base::Unretained(this), callback, desired_size); |  | 
|  232  |  | 
|  233   if (history_service_) { |  | 
|  234     return history_service_->GetFaviconForID( |  | 
|  235         favicon_id, desired_size, callback_runner, tracker); |  | 
|  236   } |  | 
|  237   return RunWithEmptyResultAsync(callback_runner, tracker); |  | 
|  238 } |  | 
|  239  |  | 
|  240 void FaviconService::SetFaviconOutOfDateForPage(const GURL& page_url) { |  | 
|  241   if (history_service_) |  | 
|  242     history_service_->SetFaviconsOutOfDateForPage(page_url); |  | 
|  243 } |  | 
|  244  |  | 
|  245 void FaviconService::SetImportedFavicons( |  | 
|  246     const favicon_base::FaviconUsageDataList& favicon_usage) { |  | 
|  247   if (history_service_) |  | 
|  248     history_service_->SetImportedFavicons(favicon_usage); |  | 
|  249 } |  | 
|  250  |  | 
|  251 void FaviconService::MergeFavicon( |  | 
|  252     const GURL& page_url, |  | 
|  253     const GURL& icon_url, |  | 
|  254     favicon_base::IconType icon_type, |  | 
|  255     scoped_refptr<base::RefCountedMemory> bitmap_data, |  | 
|  256     const gfx::Size& pixel_size) { |  | 
|  257   if (history_service_) { |  | 
|  258     history_service_->MergeFavicon(page_url, icon_url, icon_type, bitmap_data, |  | 
|  259                                    pixel_size); |  | 
|  260   } |  | 
|  261 } |  | 
|  262  |  | 
|  263 void FaviconService::SetFavicons(const GURL& page_url, |  | 
|  264                                  const GURL& icon_url, |  | 
|  265                                  favicon_base::IconType icon_type, |  | 
|  266                                  const gfx::Image& image) { |  | 
|  267   if (!history_service_) |  | 
|  268     return; |  | 
|  269  |  | 
|  270   gfx::ImageSkia image_skia = image.AsImageSkia(); |  | 
|  271   image_skia.EnsureRepsForSupportedScales(); |  | 
|  272   const std::vector<gfx::ImageSkiaRep>& image_reps = image_skia.image_reps(); |  | 
|  273   std::vector<SkBitmap> bitmaps; |  | 
|  274   const std::vector<float> favicon_scales = favicon_base::GetFaviconScales(); |  | 
|  275   for (size_t i = 0; i < image_reps.size(); ++i) { |  | 
|  276     // Don't save if the scale isn't one of supported favicon scales. |  | 
|  277     if (std::find(favicon_scales.begin(), |  | 
|  278                   favicon_scales.end(), |  | 
|  279                   image_reps[i].scale()) == favicon_scales.end()) { |  | 
|  280       continue; |  | 
|  281     } |  | 
|  282     bitmaps.push_back(image_reps[i].sk_bitmap()); |  | 
|  283   } |  | 
|  284   history_service_->SetFavicons(page_url, icon_type, icon_url, bitmaps); |  | 
|  285 } |  | 
|  286  |  | 
|  287 void FaviconService::UnableToDownloadFavicon(const GURL& icon_url) { |  | 
|  288   MissingFaviconURLHash url_hash = base::Hash(icon_url.spec()); |  | 
|  289   missing_favicon_urls_.insert(url_hash); |  | 
|  290 } |  | 
|  291  |  | 
|  292 bool FaviconService::WasUnableToDownloadFavicon(const GURL& icon_url) const { |  | 
|  293   MissingFaviconURLHash url_hash = base::Hash(icon_url.spec()); |  | 
|  294   return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end(); |  | 
|  295 } |  | 
|  296  |  | 
|  297 void FaviconService::ClearUnableToDownloadFavicons() { |  | 
|  298   missing_favicon_urls_.clear(); |  | 
|  299 } |  | 
|  300  |  | 
|  301 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURLImpl( |  | 
|  302     const GURL& page_url, |  | 
|  303     int icon_types, |  | 
|  304     const std::vector<int>& desired_sizes_in_pixel, |  | 
|  305     const favicon_base::FaviconResultsCallback& callback, |  | 
|  306     base::CancelableTaskTracker* tracker) { |  | 
|  307   if (favicon_client_ && favicon_client_->IsNativeApplicationURL(page_url)) { |  | 
|  308     return favicon_client_->GetFaviconForNativeApplicationURL( |  | 
|  309         page_url, desired_sizes_in_pixel, callback, tracker); |  | 
|  310   } |  | 
|  311   if (history_service_) { |  | 
|  312     return history_service_->GetFaviconsForURL(page_url, |  | 
|  313                                                icon_types, |  | 
|  314                                                desired_sizes_in_pixel, |  | 
|  315                                                callback, |  | 
|  316                                                tracker); |  | 
|  317   } |  | 
|  318   return RunWithEmptyResultAsync(callback, tracker); |  | 
|  319 } |  | 
|  320  |  | 
|  321 void FaviconService::RunFaviconImageCallbackWithBitmapResults( |  | 
|  322     const favicon_base::FaviconImageCallback& callback, |  | 
|  323     int desired_size_in_dip, |  | 
|  324     const std::vector<favicon_base::FaviconRawBitmapResult>& |  | 
|  325         favicon_bitmap_results) { |  | 
|  326   TRACE_EVENT0("browser", |  | 
|  327                "FaviconService::RunFaviconImageCallbackWithBitmapResults"); |  | 
|  328   favicon_base::FaviconImageResult image_result; |  | 
|  329   image_result.image = favicon_base::SelectFaviconFramesFromPNGs( |  | 
|  330       favicon_bitmap_results, |  | 
|  331       favicon_base::GetFaviconScales(), |  | 
|  332       desired_size_in_dip); |  | 
|  333   favicon_base::SetFaviconColorSpace(&image_result.image); |  | 
|  334  |  | 
|  335   image_result.icon_url = image_result.image.IsEmpty() ? |  | 
|  336       GURL() : favicon_bitmap_results[0].icon_url; |  | 
|  337   callback.Run(image_result); |  | 
|  338 } |  | 
|  339  |  | 
|  340 void FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults( |  | 
|  341     const favicon_base::FaviconRawBitmapCallback& callback, |  | 
|  342     int desired_size_in_pixel, |  | 
|  343     const std::vector<favicon_base::FaviconRawBitmapResult>& |  | 
|  344         favicon_bitmap_results) { |  | 
|  345   TRACE_EVENT0("browser", |  | 
|  346                "FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults"); |  | 
|  347   callback.Run( |  | 
|  348       ResizeFaviconBitmapResult(favicon_bitmap_results, desired_size_in_pixel)); |  | 
|  349 } |  | 
|  350  |  | 
|  351 }  // namespace favicon |   16 }  // namespace favicon | 
| OLD | NEW |