 Chromium Code Reviews
 Chromium Code Reviews Issue 1261143004:
  Implement manifest icon downloader  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1261143004:
  Implement manifest icon downloader  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| Index: chrome/browser/manifest/manifest_icon_downloader.cc | 
| diff --git a/chrome/browser/manifest/manifest_icon_downloader.cc b/chrome/browser/manifest/manifest_icon_downloader.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..0e40029d21df1a25689acf2fe3e2170cceba5f67 | 
| --- /dev/null | 
| +++ b/chrome/browser/manifest/manifest_icon_downloader.cc | 
| @@ -0,0 +1,122 @@ | 
| +// Copyright 2015 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "chrome/browser/manifest/manifest_icon_downloader.h" | 
| + | 
| +#include "chrome/browser/manifest/manifest_icon_selector.h" | 
| +#include "content/public/browser/browser_thread.h" | 
| +#include "content/public/browser/web_contents.h" | 
| +#include "skia/ext/image_operations.h" | 
| +#include "ui/gfx/screen.h" | 
| + | 
| +ManifestIconDownloader::ManifestIconDownloader( | 
| + content::WebContents* web_contents) | 
| + : WebContentsObserver(web_contents) { | 
| +} | 
| + | 
| +bool ManifestIconDownloader::Download( | 
| + const GURL& icon_url, | 
| + int ideal_icon_size_in_dp, | 
| + const ManifestIconDownloader::IconFetchCallback& callback) { | 
| + if (!web_contents() || !icon_url.is_valid()) return false; | 
| + | 
| + const gfx::Screen* screen = | 
| + gfx::Screen::GetScreenFor(web_contents()->GetNativeView()); | 
| + const float device_scale_factor = | 
| + screen->GetPrimaryDisplay().device_scale_factor(); | 
| + const float ideal_icon_size_in_px = | 
| + ideal_icon_size_in_dp * device_scale_factor; | 
| + | 
| + web_contents()->DownloadImage( | 
| + icon_url, | 
| + false, // is_favicon | 
| + 0, // max_bitmap_size - 0 means no maximum size. | 
| + false, // bypass_cache | 
| + base::Bind(&ManifestIconDownloader::OnIconFetched, | 
| + ideal_icon_size_in_px, | 
| + callback)); | 
| + return true; | 
| +} | 
| + | 
| +void ManifestIconDownloader::OnIconFetched( | 
| + int ideal_icon_size_in_px, | 
| + const ManifestIconDownloader::IconFetchCallback& callback, | 
| + int id, | 
| + int http_status_code, | 
| + const GURL& url, | 
| + const std::vector<SkBitmap>& bitmaps, | 
| + const std::vector<gfx::Size>& sizes) { | 
| + const int closest_index = FindClosestBitmapIndex( | 
| 
mlamouri (slow - plz ping)
2015/08/10 15:08:08
nit: add |DCHECK_CURRENTLY_ON(content::BrowserThre
 
Lalit Maganti
2015/08/10 16:55:45
Done.
 | 
| + ideal_icon_size_in_px, bitmaps); | 
| + | 
| + if (closest_index == -1) { | 
| + callback.Run(SkBitmap()); | 
| + return; | 
| + } | 
| + | 
| + const SkBitmap& chosen = bitmaps[closest_index]; | 
| + if (chosen.height() != ideal_icon_size_in_px) { | 
| + content::BrowserThread::PostTask( | 
| + content::BrowserThread::IO, | 
| + FROM_HERE, | 
| + base::Bind(&ManifestIconDownloader::ScaleIcon, | 
| + ideal_icon_size_in_px, | 
| + chosen, | 
| + callback)); | 
| + return; | 
| + } | 
| + | 
| + callback.Run(chosen); | 
| +} | 
| + | 
| +void ManifestIconDownloader::ScaleIcon( | 
| + const int ideal_icon_size_in_px, | 
| + const SkBitmap& bitmap, | 
| + const ManifestIconDownloader::IconFetchCallback& callback) { | 
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 
| + | 
| + const SkBitmap& scaled = skia::ImageOperations::Resize( | 
| + bitmap, | 
| + skia::ImageOperations::RESIZE_BEST, | 
| + ideal_icon_size_in_px, | 
| + ideal_icon_size_in_px); | 
| + content::BrowserThread::PostTask( | 
| + content::BrowserThread::UI, | 
| + FROM_HERE, | 
| + base::Bind(callback, scaled)); | 
| +} | 
| + | 
| +void ManifestIconDownloader::RunCallbackOnUIThread( | 
| 
mlamouri (slow - plz ping)
2015/08/10 15:08:08
You don't actually use that, maybe you could remov
 
Lalit Maganti
2015/08/10 16:55:45
Done.
 | 
| + const ManifestIconDownloader::IconFetchCallback& callback, | 
| + const SkBitmap& bitmap) { | 
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 
| + callback.Run(bitmap); | 
| +} | 
| + | 
| +int ManifestIconDownloader::FindClosestBitmapIndex( | 
| + int ideal_icon_size_in_px, | 
| + const std::vector<SkBitmap>& bitmaps) { | 
| + // This algorithm searches for an icon equal to the ideal size. Failing that, | 
| + // it picks the smallest icon larger than the ideal size to downscale. Icons | 
| + // which are not in a square shape are ignored. | 
| + const SkBitmap* best_upper = nullptr; | 
| + int best_upper_index = -1; | 
| + | 
| + for (size_t i = 0; i < bitmaps.size(); ++i) { | 
| + const SkBitmap& current_bitmap = bitmaps[i]; | 
| + if (current_bitmap.height() != current_bitmap.width()) | 
| + continue; | 
| + | 
| + if (current_bitmap.height() == ideal_icon_size_in_px) | 
| + return i; | 
| + | 
| + if (current_bitmap.height() > ideal_icon_size_in_px && | 
| + (!best_upper || current_bitmap.height() < best_upper->height())) { | 
| + best_upper = ¤t_bitmap; | 
| + best_upper_index = i; | 
| + } | 
| + } | 
| + | 
| + return best_upper_index; | 
| +} |