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( |