| 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..8f091e0058fdc3adce6fb599c286c43a059f3a45
|
| --- /dev/null
|
| +++ b/chrome/browser/manifest/manifest_icon_downloader.cc
|
| @@ -0,0 +1,94 @@
|
| +// 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/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,
|
| + 0,
|
| + false,
|
| + 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(
|
| + ideal_icon_size_in_px, bitmaps);
|
| +
|
| + if (closest_index == -1) {
|
| + callback.Run(SkBitmap());
|
| + return;
|
| + }
|
| +
|
| + const SkBitmap& scaled = skia::ImageOperations::Resize(
|
| + bitmaps[closest_index],
|
| + skia::ImageOperations::RESIZE_BEST,
|
| + ideal_icon_size_in_px,
|
| + ideal_icon_size_in_px);
|
| + callback.Run(scaled);
|
| +}
|
| +
|
| +int ManifestIconDownloader::FindClosestBitmapIndex(
|
| + int ideal_icon_size_in_px,
|
| + const std::vector<SkBitmap>& bitmaps) {
|
| + if (bitmaps.empty())
|
| + return -1;
|
| +
|
| + // 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];
|
| + int height = current_bitmap.height();
|
| + if (height != current_bitmap.width())
|
| + continue;
|
| +
|
| + if (height == ideal_icon_size_in_px)
|
| + return i;
|
| +
|
| + if (height > ideal_icon_size_in_px &&
|
| + (!best_upper || height < best_upper->height())) {
|
| + best_upper = ¤t_bitmap;
|
| + best_upper_index = i;
|
| + }
|
| + }
|
| +
|
| + return best_upper_index;
|
| +}
|
|
|