| Index: chrome/browser/extensions/bookmark_app_helper.cc
|
| diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc
|
| index c9fcb08b375be83bad47cac0026bc1a85e24a863..bf2cd70db8338aae1c4d1fd64fdb769061f7a1ca 100644
|
| --- a/chrome/browser/extensions/bookmark_app_helper.cc
|
| +++ b/chrome/browser/extensions/bookmark_app_helper.cc
|
| @@ -112,6 +112,64 @@ void OnIconsLoaded(
|
| callback.Run(web_app_info);
|
| }
|
|
|
| +std::set<int> SizesToGenerate() {
|
| + // Generate container icons from smaller icons.
|
| + const int kIconSizesToGenerate[] = {
|
| + extension_misc::EXTENSION_ICON_SMALL,
|
| + extension_misc::EXTENSION_ICON_MEDIUM,
|
| + };
|
| + return std::set<int>(kIconSizesToGenerate,
|
| + kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
|
| +}
|
| +
|
| +void GenerateIcons(std::set<int> generate_sizes,
|
| + const GURL& app_url,
|
| + SkColor generated_icon_color,
|
| + std::map<int, SkBitmap>* bitmap_map) {
|
| + // The letter that will be painted on the generated icon.
|
| + char icon_letter = ' ';
|
| + std::string domain_and_registry(
|
| + net::registry_controlled_domains::GetDomainAndRegistry(
|
| + app_url,
|
| + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
|
| + if (!domain_and_registry.empty()) {
|
| + icon_letter = domain_and_registry[0];
|
| + } else if (!app_url.host().empty()) {
|
| + icon_letter = app_url.host()[0];
|
| + }
|
| +
|
| + // If no color has been specified, use a dark gray so it will stand out on the
|
| + // black shelf.
|
| + if (generated_icon_color == SK_ColorTRANSPARENT)
|
| + generated_icon_color = SK_ColorDKGRAY;
|
| +
|
| + for (std::set<int>::const_iterator it = generate_sizes.begin();
|
| + it != generate_sizes.end(); ++it) {
|
| + extensions::BookmarkAppHelper::GenerateIcon(
|
| + bitmap_map, *it, generated_icon_color, icon_letter);
|
| + // Also generate the 2x resource for this size.
|
| + extensions::BookmarkAppHelper::GenerateIcon(
|
| + bitmap_map, *it * 2, generated_icon_color, icon_letter);
|
| + }
|
| +}
|
| +
|
| +void ReplaceWebAppIcons(std::map<int, SkBitmap> bitmap_map,
|
| + WebApplicationInfo* web_app_info) {
|
| + web_app_info->icons.clear();
|
| +
|
| + // Populate the icon data into the WebApplicationInfo we are using to
|
| + // install the bookmark app.
|
| + for (std::map<int, SkBitmap>::const_iterator bitmap_map_it =
|
| + bitmap_map.begin();
|
| + bitmap_map_it != bitmap_map.end(); ++bitmap_map_it) {
|
| + WebApplicationInfo::IconInfo icon_info;
|
| + icon_info.data = bitmap_map_it->second;
|
| + icon_info.width = icon_info.data.width();
|
| + icon_info.height = icon_info.data.height();
|
| + web_app_info->icons.push_back(icon_info);
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace extensions {
|
| @@ -145,42 +203,6 @@ void BookmarkAppHelper::UpdateWebAppInfoFromManifest(
|
| }
|
|
|
| // static
|
| -std::map<int, SkBitmap> BookmarkAppHelper::ConstrainBitmapsToSizes(
|
| - const std::vector<SkBitmap>& bitmaps,
|
| - const std::set<int>& sizes) {
|
| - std::map<int, SkBitmap> output_bitmaps;
|
| - std::map<int, SkBitmap> ordered_bitmaps;
|
| - for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin();
|
| - it != bitmaps.end();
|
| - ++it) {
|
| - DCHECK(it->width() == it->height());
|
| - ordered_bitmaps[it->width()] = *it;
|
| - }
|
| -
|
| - std::set<int>::const_iterator sizes_it = sizes.begin();
|
| - std::map<int, SkBitmap>::const_iterator bitmaps_it = ordered_bitmaps.begin();
|
| - while (sizes_it != sizes.end() && bitmaps_it != ordered_bitmaps.end()) {
|
| - int size = *sizes_it;
|
| - // Find the closest not-smaller bitmap.
|
| - bitmaps_it = ordered_bitmaps.lower_bound(size);
|
| - ++sizes_it;
|
| - // Ensure the bitmap is valid and smaller than the next allowed size.
|
| - if (bitmaps_it != ordered_bitmaps.end() &&
|
| - (sizes_it == sizes.end() || bitmaps_it->second.width() < *sizes_it)) {
|
| - // Resize the bitmap if it does not exactly match the desired size.
|
| - output_bitmaps[size] = bitmaps_it->second.width() == size
|
| - ? bitmaps_it->second
|
| - : skia::ImageOperations::Resize(
|
| - bitmaps_it->second,
|
| - skia::ImageOperations::RESIZE_LANCZOS3,
|
| - size,
|
| - size);
|
| - }
|
| - }
|
| - return output_bitmaps;
|
| -}
|
| -
|
| -// static
|
| void BookmarkAppHelper::GenerateIcon(std::map<int, SkBitmap>* bitmaps,
|
| int output_size,
|
| SkColor color,
|
| @@ -260,12 +282,6 @@ void BookmarkAppHelper::OnIconsDownloaded(
|
| return;
|
| }
|
|
|
| - // Add the downloaded icons. Extensions only allow certain icon sizes. First
|
| - // populate icons that match the allowed sizes exactly and then downscale
|
| - // remaining icons to the closest allowed size that doesn't yet have an icon.
|
| - std::set<int> allowed_sizes(extension_misc::kExtensionIconSizes,
|
| - extension_misc::kExtensionIconSizes +
|
| - extension_misc::kNumExtensionIconSizes);
|
| std::vector<SkBitmap> downloaded_icons;
|
| for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin();
|
| map_it != bitmaps.end();
|
| @@ -291,70 +307,33 @@ void BookmarkAppHelper::OnIconsDownloaded(
|
| downloaded_icons.push_back(icon);
|
| }
|
|
|
| - web_app_info_.icons.clear();
|
| -
|
| - // If there are icons that don't match the accepted icon sizes, find the
|
| - // closest bigger icon to the accepted sizes and resize the icon to it. An
|
| - // icon will be resized and used for at most one size.
|
| - std::map<int, SkBitmap> resized_bitmaps(
|
| - ConstrainBitmapsToSizes(downloaded_icons, allowed_sizes));
|
| + // Add the downloaded icons. Extensions only allow certain icon sizes. First
|
| + // populate icons that match the allowed sizes exactly and then downscale
|
| + // remaining icons to the closest allowed size that doesn't yet have an icon.
|
| + std::set<int> allowed_sizes(extension_misc::kExtensionIconSizes,
|
| + extension_misc::kExtensionIconSizes +
|
| + extension_misc::kNumExtensionIconSizes);
|
|
|
| - // Generate container icons from smaller icons.
|
| - const int kIconSizesToGenerate[] = {extension_misc::EXTENSION_ICON_SMALL,
|
| - extension_misc::EXTENSION_ICON_MEDIUM, };
|
| - const std::set<int> generate_sizes(
|
| - kIconSizesToGenerate,
|
| - kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
|
| -
|
| - // Only generate icons if larger icons don't exist. This means the app
|
| - // launcher and the taskbar will do their best downsizing large icons and
|
| - // these icons are only generated as a last resort against upscaling a smaller
|
| - // icon.
|
| - if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) ==
|
| - resized_bitmaps.end()) {
|
| - GURL app_url = web_app_info_.app_url;
|
| -
|
| - // The letter that will be painted on the generated icon.
|
| - char icon_letter = ' ';
|
| - std::string domain_and_registry(
|
| - net::registry_controlled_domains::GetDomainAndRegistry(
|
| - app_url,
|
| - net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
|
| - if (!domain_and_registry.empty()) {
|
| - icon_letter = domain_and_registry[0];
|
| - } else if (!app_url.host().empty()) {
|
| - icon_letter = app_url.host()[0];
|
| - }
|
| + web_app_info_.generated_icon_color = SK_ColorTRANSPARENT;
|
| + // Determine the color that will be used for the icon's background. For this
|
| + // the dominant color of the first icon found is used.
|
| + if (downloaded_icons.size()) {
|
| + color_utils::GridSampler sampler;
|
| + web_app_info_.generated_icon_color =
|
| + color_utils::CalculateKMeanColorOfBitmap(downloaded_icons[0]);
|
| + }
|
|
|
| - // The color that will be used for the icon's background.
|
| - SkColor background_color = SK_ColorBLACK;
|
| - if (resized_bitmaps.size()) {
|
| - color_utils::GridSampler sampler;
|
| - background_color = color_utils::CalculateKMeanColorOfBitmap(
|
| - resized_bitmaps.begin()->second);
|
| - }
|
| + std::set<int> generate_sizes = SizesToGenerate();
|
|
|
| - for (std::set<int>::const_iterator it = generate_sizes.begin();
|
| - it != generate_sizes.end();
|
| - ++it) {
|
| - GenerateIcon(&resized_bitmaps, *it, background_color, icon_letter);
|
| - // Also generate the 2x resource for this size.
|
| - GenerateIcon(&resized_bitmaps, *it * 2, background_color, icon_letter);
|
| - }
|
| - }
|
| + std::map<int, SkBitmap> generated_icons;
|
| + // Icons are always generated, replacing the icons that were downloaded. This
|
| + // is done so that the icons are consistent across machines.
|
| + // TODO(benwells): Use blob sync once it is available to sync the downloaded
|
| + // icons, and then only generate when there are required sizes missing.
|
| + GenerateIcons(generate_sizes, web_app_info_.app_url,
|
| + web_app_info_.generated_icon_color, &generated_icons);
|
|
|
| - // Populate the icon data into the WebApplicationInfo we are using to
|
| - // install the bookmark app.
|
| - for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it =
|
| - resized_bitmaps.begin();
|
| - resized_bitmaps_it != resized_bitmaps.end();
|
| - ++resized_bitmaps_it) {
|
| - WebApplicationInfo::IconInfo icon_info;
|
| - icon_info.data = resized_bitmaps_it->second;
|
| - icon_info.width = icon_info.data.width();
|
| - icon_info.height = icon_info.data.height();
|
| - web_app_info_.icons.push_back(icon_info);
|
| - }
|
| + ReplaceWebAppIcons(generated_icons, &web_app_info_);
|
|
|
| // Install the app.
|
| crx_installer_->InstallWebApp(web_app_info_);
|
| @@ -384,11 +363,18 @@ void BookmarkAppHelper::Observe(int type,
|
| }
|
|
|
| void CreateOrUpdateBookmarkApp(ExtensionService* service,
|
| - WebApplicationInfo& web_app_info) {
|
| + WebApplicationInfo* web_app_info) {
|
| scoped_refptr<extensions::CrxInstaller> installer(
|
| extensions::CrxInstaller::CreateSilent(service));
|
| installer->set_error_on_unsupported_requirements(true);
|
| - installer->InstallWebApp(web_app_info);
|
| + if (web_app_info->icons.empty()) {
|
| + std::map<int, SkBitmap> bitmap_map;
|
| + GenerateIcons(SizesToGenerate(), web_app_info->app_url,
|
| + web_app_info->generated_icon_color, &bitmap_map);
|
| + ReplaceWebAppIcons(bitmap_map, web_app_info);
|
| + }
|
| +
|
| + installer->InstallWebApp(*web_app_info);
|
| }
|
|
|
| void GetWebApplicationInfoFromApp(
|
|
|