diff options
31 files changed, 304 insertions, 178 deletions
diff --git a/chrome/browser/extensions/api/extension_action/extension_action_api.cc b/chrome/browser/extensions/api/extension_action/extension_action_api.cc index fb05935..de3d55c 100644 --- a/chrome/browser/extensions/api/extension_action/extension_action_api.cc +++ b/chrome/browser/extensions/api/extension_action/extension_action_api.cc @@ -26,10 +26,10 @@ #include "extensions/browser/extension_function_registry.h" #include "extensions/browser/extension_host.h" #include "extensions/browser/extension_registry.h" -#include "extensions/browser/image_util.h" #include "extensions/browser/notification_types.h" #include "extensions/common/error_utils.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/image_util.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" diff --git a/chrome/browser/extensions/app_sync_data.cc b/chrome/browser/extensions/app_sync_data.cc index 1ecbb24c..6ee99da 100644 --- a/chrome/browser/extensions/app_sync_data.cc +++ b/chrome/browser/extensions/app_sync_data.cc @@ -4,6 +4,7 @@ #include "chrome/browser/extensions/app_sync_data.h" +#include "chrome/common/extensions/manifest_handlers/app_icon_color_info.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "extensions/common/extension.h" #include "sync/api/sync_data.h" @@ -41,6 +42,7 @@ AppSyncData::AppSyncData(const Extension& extension, if (extension.from_bookmark()) { bookmark_app_description_ = extension.description(); bookmark_app_url_ = AppLaunchInfo::GetLaunchWebURL(&extension).spec(); + bookmark_app_icon_color_ = AppIconColorInfo::GetIconColorString(&extension); } } @@ -84,6 +86,9 @@ void AppSyncData::PopulateAppSpecifics(sync_pb::AppSpecifics* specifics) const { if (!bookmark_app_description_.empty()) specifics->set_bookmark_app_description(bookmark_app_description_); + if (!bookmark_app_icon_color_.empty()) + specifics->set_bookmark_app_icon_color(bookmark_app_icon_color_); + extension_sync_data_.PopulateExtensionSpecifics( specifics->mutable_extension()); } @@ -101,6 +106,7 @@ void AppSyncData::PopulateFromAppSpecifics( bookmark_app_url_ = specifics.bookmark_app_url(); bookmark_app_description_ = specifics.bookmark_app_description(); + bookmark_app_icon_color_ = specifics.bookmark_app_icon_color(); } void AppSyncData::PopulateFromSyncData(const syncer::SyncData& sync_data) { diff --git a/chrome/browser/extensions/app_sync_data.h b/chrome/browser/extensions/app_sync_data.h index 5bf97b4..82f49ea 100644 --- a/chrome/browser/extensions/app_sync_data.h +++ b/chrome/browser/extensions/app_sync_data.h @@ -9,6 +9,7 @@ #include "extensions/common/constants.h" #include "sync/api/string_ordinal.h" #include "sync/api/sync_change.h" +#include "third_party/skia/include/core/SkColor.h" namespace syncer { class SyncData; @@ -70,6 +71,10 @@ class AppSyncData { return bookmark_app_description_; } + const std::string& bookmark_app_icon_color() const { + return bookmark_app_icon_color_; + } + private: // Convert an AppSyncData back out to a sync structure. void PopulateAppSpecifics(sync_pb::AppSpecifics* specifics) const; @@ -85,6 +90,7 @@ class AppSyncData { extensions::LaunchType launch_type_; std::string bookmark_app_url_; std::string bookmark_app_description_; + std::string bookmark_app_icon_color_; }; } // namespace extensions diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc index c9fcb08..bf2cd70 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( diff --git a/chrome/browser/extensions/bookmark_app_helper.h b/chrome/browser/extensions/bookmark_app_helper.h index 434def6..31442a6 100644 --- a/chrome/browser/extensions/bookmark_app_helper.h +++ b/chrome/browser/extensions/bookmark_app_helper.h @@ -107,7 +107,7 @@ class BookmarkAppHelper : public content::NotificationObserver { // Creates or updates a bookmark app from the given |web_app_info|. Icons will // not be downloaded so only supplied icon data will be used. void CreateOrUpdateBookmarkApp(ExtensionService* service, - WebApplicationInfo& web_app_info); + WebApplicationInfo* web_app_info); // Retrieves the WebApplicationInfo that represents a given bookmark app. // |callback| will be called with a WebApplicationInfo which is populated with diff --git a/chrome/browser/extensions/bookmark_app_helper_unittest.cc b/chrome/browser/extensions/bookmark_app_helper_unittest.cc index 7afd55a..36cab55 100644 --- a/chrome/browser/extensions/bookmark_app_helper_unittest.cc +++ b/chrome/browser/extensions/bookmark_app_helper_unittest.cc @@ -83,14 +83,6 @@ SkBitmap CreateSquareBitmapWithColor(int size, SkColor color) { return bitmap; } -void ValidateBitmapSizeAndColor(SkBitmap bitmap, int size, SkColor color) { - // Obtain pixel lock to access pixels. - SkAutoLockPixels lock(bitmap); - EXPECT_EQ(color, bitmap.getColor(0, 0)); - EXPECT_EQ(size, bitmap.width()); - EXPECT_EQ(size, bitmap.height()); -} - WebApplicationInfo::IconInfo CreateIconInfoWithBitmap(int size, SkColor color) { WebApplicationInfo::IconInfo icon_info; icon_info.width = size; @@ -234,9 +226,10 @@ TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkAppNoContents) { EXPECT_EQ(kAppTitle, extension->name()); EXPECT_EQ(kAppDescription, extension->description()); EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension)); - EXPECT_FALSE( - IconsInfo::GetIconResource( - extension, kIconSizeTiny, ExtensionIconSet::MATCH_EXACTLY).empty()); + // The tiny icon should have been removed and only the generated ones used. + EXPECT_TRUE( + IconsInfo::GetIconResource(extension, kIconSizeTiny, + ExtensionIconSet::MATCH_EXACTLY).empty()); EXPECT_FALSE( IconsInfo::GetIconResource( extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY).empty()); @@ -262,7 +255,7 @@ TEST_F(BookmarkAppHelperExtensionServiceTest, CreateAndUpdateBookmarkApp) { web_app_info.icons.push_back( CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED)); - extensions::CreateOrUpdateBookmarkApp(service_, web_app_info); + extensions::CreateOrUpdateBookmarkApp(service_, &web_app_info); base::RunLoop().RunUntilIdle(); { @@ -281,7 +274,7 @@ TEST_F(BookmarkAppHelperExtensionServiceTest, CreateAndUpdateBookmarkApp) { web_app_info.title = base::UTF8ToUTF16(kAlternativeAppTitle); web_app_info.icons[0] = CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorRED); - extensions::CreateOrUpdateBookmarkApp(service_, web_app_info); + extensions::CreateOrUpdateBookmarkApp(service_, &web_app_info); base::RunLoop().RunUntilIdle(); { @@ -312,7 +305,7 @@ TEST_F(BookmarkAppHelperExtensionServiceTest, GetWebApplicationInfo) { web_app_info.icons.push_back( CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorRED)); - extensions::CreateOrUpdateBookmarkApp(service_, web_app_info); + extensions::CreateOrUpdateBookmarkApp(service_, &web_app_info); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1u, registry()->enabled_extensions().size()); @@ -364,45 +357,6 @@ TEST_F(BookmarkAppHelperTest, UpdateWebAppInfoFromManifest) { EXPECT_EQ(GURL(kAppIcon3), web_app_info.icons[1].url); } -TEST_F(BookmarkAppHelperTest, ConstrainBitmapsToSizes) { - std::set<int> desired_sizes; - desired_sizes.insert(16); - desired_sizes.insert(32); - desired_sizes.insert(128); - desired_sizes.insert(256); - - { - std::vector<SkBitmap> bitmaps; - bitmaps.push_back(CreateSquareBitmapWithColor(16, SK_ColorRED)); - bitmaps.push_back(CreateSquareBitmapWithColor(32, SK_ColorGREEN)); - bitmaps.push_back(CreateSquareBitmapWithColor(48, SK_ColorBLUE)); - bitmaps.push_back(CreateSquareBitmapWithColor(144, SK_ColorYELLOW)); - - std::map<int, SkBitmap> results( - BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes)); - - EXPECT_EQ(3u, results.size()); - ValidateBitmapSizeAndColor(results[16], 16, SK_ColorRED); - ValidateBitmapSizeAndColor(results[32], 32, SK_ColorGREEN); - ValidateBitmapSizeAndColor(results[128], 128, SK_ColorYELLOW); - } - { - std::vector<SkBitmap> bitmaps; - bitmaps.push_back(CreateSquareBitmapWithColor(512, SK_ColorRED)); - bitmaps.push_back(CreateSquareBitmapWithColor(18, SK_ColorGREEN)); - bitmaps.push_back(CreateSquareBitmapWithColor(33, SK_ColorBLUE)); - bitmaps.push_back(CreateSquareBitmapWithColor(17, SK_ColorYELLOW)); - - std::map<int, SkBitmap> results( - BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes)); - - EXPECT_EQ(3u, results.size()); - ValidateBitmapSizeAndColor(results[16], 16, SK_ColorYELLOW); - ValidateBitmapSizeAndColor(results[32], 32, SK_ColorBLUE); - ValidateBitmapSizeAndColor(results[256], 256, SK_ColorRED); - } -} - TEST_F(BookmarkAppHelperTest, IsValidBookmarkAppUrl) { EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("https://www.chromium.org"))); EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("http://www.chromium.org/path"))); diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc index d6da449..04becdc 100644 --- a/chrome/browser/extensions/convert_web_app.cc +++ b/chrome/browser/extensions/convert_web_app.cc @@ -25,6 +25,7 @@ #include "extensions/common/constants.h" #include "extensions/common/extension.h" #include "extensions/common/file_util.h" +#include "extensions/common/image_util.h" #include "extensions/common/manifest_constants.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/codec/png_codec.h" @@ -106,6 +107,10 @@ scoped_refptr<Extension> ConvertWebAppToExtension( root->SetString(keys::kVersion, ConvertTimeToExtensionVersion(create_time)); root->SetString(keys::kDescription, base::UTF16ToUTF8(web_app.description)); root->SetString(keys::kLaunchWebURL, web_app.app_url.spec()); + if (web_app.generated_icon_color != SK_ColorTRANSPARENT) { + root->SetString(keys::kAppIconColor, image_util::GenerateCSSColorString( + web_app.generated_icon_color)); + } // Add the icons. base::DictionaryValue* icons = new base::DictionaryValue(); diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc index 895da02..cd8d3aa 100644 --- a/chrome/browser/extensions/extension_sync_service.cc +++ b/chrome/browser/extensions/extension_sync_service.cc @@ -32,6 +32,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_icon_set.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/image_util.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/icons_handler.h" #include "sync/api/sync_change.h" @@ -56,7 +57,7 @@ void OnWebApplicationInfoLoaded( // Use the old icons if they exist. synced_info.icons = loaded_info.icons; - CreateOrUpdateBookmarkApp(extension_service.get(), synced_info); + CreateOrUpdateBookmarkApp(extension_service.get(), &synced_info); } } // namespace @@ -388,10 +389,15 @@ void ExtensionSyncService::ProcessBookmarkAppSyncData( base::UTF8ToUTF16(app_sync_data.extension_sync_data().name()); web_app_info.description = base::UTF8ToUTF16(app_sync_data.bookmark_app_description()); + if (!app_sync_data.bookmark_app_icon_color().empty()) { + extensions::image_util::ParseCSSColorString( + app_sync_data.bookmark_app_icon_color(), + &web_app_info.generated_icon_color); + } // If the bookmark app already exists, keep the old icons. if (!extension) { - CreateOrUpdateBookmarkApp(extension_service_, web_app_info); + CreateOrUpdateBookmarkApp(extension_service_, &web_app_info); } else { app_sync_data.extension_sync_data().name(); GetWebApplicationInfoFromApp(profile_, diff --git a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc index 8cf9393..58d590a 100644 --- a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc @@ -443,7 +443,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, BookmarkApp) { extensions::NOTIFICATION_CRX_INSTALLER_DONE, content::NotificationService::AllSources()); extensions::CreateOrUpdateBookmarkApp(GetExtensionService(GetProfile(0)), - web_app_info); + &web_app_info); windowed_observer.Wait(); EXPECT_EQ(num_extensions, GetExtensionRegistry(GetProfile(0))->enabled_extensions().size()); @@ -453,7 +453,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, BookmarkApp) { extensions::NOTIFICATION_CRX_INSTALLER_DONE, content::NotificationService::AllSources()); extensions::CreateOrUpdateBookmarkApp(GetExtensionService(verifier()), - web_app_info); + &web_app_info); windowed_observer.Wait(); EXPECT_EQ(num_extensions, GetExtensionRegistry(verifier())->enabled_extensions().size()); diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index 53a2039..485ebb1 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm @@ -585,7 +585,7 @@ void BrowserWindowCocoa::ShowBookmarkAppBubble( if (![original_title isEqualToString:new_title]) { WebApplicationInfo new_web_app_info(web_app_info); new_web_app_info.title = base::SysNSStringToUTF16(new_title); - extensions::CreateOrUpdateBookmarkApp(service, new_web_app_info); + extensions::CreateOrUpdateBookmarkApp(service, &new_web_app_info); } extensions::ExtensionRegistry* registry = diff --git a/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc index 1b1e0dc..566b751 100644 --- a/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc +++ b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc @@ -273,5 +273,5 @@ void BookmarkAppBubbleView::ApplyEdits() { install_info.title = title_tf_->text(); extensions::CreateOrUpdateBookmarkApp(GetExtensionService(profile_), - install_info); + &install_info); } diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 7596433..4367f67 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -177,6 +177,8 @@ 'common/extensions/features/feature_channel.h', 'common/extensions/image_writer/image_writer_util_mac.cc', 'common/extensions/image_writer/image_writer_util_mac.h', + 'common/extensions/manifest_handlers/app_icon_color_info.cc', + 'common/extensions/manifest_handlers/app_icon_color_info.h', 'common/extensions/manifest_handlers/app_isolation_info.cc', 'common/extensions/manifest_handlers/app_isolation_info.h', 'common/extensions/manifest_handlers/app_launch_info.cc', diff --git a/chrome/common/extensions/api/_manifest_features.json b/chrome/common/extensions/api/_manifest_features.json index 72aba14..0eda5b5 100644 --- a/chrome/common/extensions/api/_manifest_features.json +++ b/chrome/common/extensions/api/_manifest_features.json @@ -20,6 +20,10 @@ "channel": "stable", "extension_types": ["shared_module"] }, + "app.icon_color": { + "channel": "stable", + "extension_types": ["hosted_app"] + }, "app.isolation": { "channel": "stable", // Platform apps always have isolated storage, thus they cannot specify it diff --git a/chrome/common/extensions/chrome_manifest_handlers.cc b/chrome/common/extensions/chrome_manifest_handlers.cc index 9194d7d..cbde83c 100644 --- a/chrome/common/extensions/chrome_manifest_handlers.cc +++ b/chrome/common/extensions/chrome_manifest_handlers.cc @@ -18,6 +18,7 @@ #include "chrome/common/extensions/api/system_indicator/system_indicator_handler.h" #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" #include "chrome/common/extensions/chrome_manifest_url_handlers.h" +#include "chrome/common/extensions/manifest_handlers/app_icon_color_info.h" #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/extensions/manifest_handlers/automation.h" @@ -37,6 +38,7 @@ namespace extensions { void RegisterChromeManifestHandlers() { DCHECK(!ManifestHandler::IsRegistrationFinalized()); (new AboutPageHandler)->Register(); + (new AppIconColorHandler)->Register(); (new AppIsolationHandler)->Register(); (new AppLaunchManifestHandler)->Register(); (new AutomationHandler)->Register(); diff --git a/chrome/common/extensions/manifest_handlers/app_icon_color_info.cc b/chrome/common/extensions/manifest_handlers/app_icon_color_info.cc new file mode 100644 index 0000000..01e83d67 --- /dev/null +++ b/chrome/common/extensions/manifest_handlers/app_icon_color_info.cc @@ -0,0 +1,84 @@ +// Copyright 2014 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/common/extensions/manifest_handlers/app_icon_color_info.h" + +#include "base/lazy_instance.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "extensions/common/image_util.h" +#include "extensions/common/manifest.h" +#include "extensions/common/manifest_constants.h" + +namespace extensions { + +namespace keys = manifest_keys; +namespace errors = manifest_errors; + +namespace { + +static base::LazyInstance<AppIconColorInfo> g_empty_app_icon_color_info = + LAZY_INSTANCE_INITIALIZER; + +const AppIconColorInfo& GetInfo(const Extension* extension) { + AppIconColorInfo* info = static_cast<AppIconColorInfo*>( + extension->GetManifestData(keys::kAppIconColor)); + return info ? *info : g_empty_app_icon_color_info.Get(); +} + +} // namespace + +AppIconColorInfo::AppIconColorInfo() : icon_color_(SK_ColorTRANSPARENT) { +} + +AppIconColorInfo::~AppIconColorInfo() { +} + +// static +SkColor AppIconColorInfo::GetIconColor(const Extension* extension) { + return GetInfo(extension).icon_color_; +} + +// static +const std::string& AppIconColorInfo::GetIconColorString( + const Extension* extension) { + return GetInfo(extension).icon_color_string_; +} + +AppIconColorHandler::AppIconColorHandler() { +} + +AppIconColorHandler::~AppIconColorHandler() { +} + +bool AppIconColorHandler::Parse(Extension* extension, base::string16* error) { + scoped_ptr<AppIconColorInfo> app_icon_color_info(new AppIconColorInfo); + + const base::Value* temp = NULL; + if (extension->manifest()->Get(keys::kAppIconColor, &temp)) { + if (!temp->GetAsString(&app_icon_color_info->icon_color_string_)) { + *error = + base::UTF8ToUTF16(extensions::manifest_errors::kInvalidAppIconColor); + return false; + } + + if (!image_util::ParseCSSColorString( + app_icon_color_info->icon_color_string_, + &app_icon_color_info->icon_color_)) { + *error = + base::UTF8ToUTF16(extensions::manifest_errors::kInvalidAppIconColor); + return false; + } + } + + extension->SetManifestData(keys::kAppIconColor, + app_icon_color_info.release()); + return true; +} + +const std::vector<std::string> AppIconColorHandler::Keys() const { + return SingleKey(keys::kAppIconColor); +} + +} // namespace extensions diff --git a/chrome/common/extensions/manifest_handlers/app_icon_color_info.h b/chrome/common/extensions/manifest_handlers/app_icon_color_info.h new file mode 100644 index 0000000..e44e301 --- /dev/null +++ b/chrome/common/extensions/manifest_handlers/app_icon_color_info.h @@ -0,0 +1,49 @@ +// Copyright 2014 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. + +#ifndef CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_APP_ICON_COLOR_INFO_H_ +#define CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_APP_ICON_COLOR_INFO_H_ + +#include "extensions/common/extension.h" +#include "extensions/common/manifest_handler.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace base { +class DictionaryValue; +} + +namespace extensions { + +// A structure to hold the parsed app icon color data. +struct AppIconColorInfo : public Extension::ManifestData { + AppIconColorInfo(); + ~AppIconColorInfo() override; + + static SkColor GetIconColor(const Extension* extension); + static const std::string& GetIconColorString(const Extension* extension); + + // The color to use if icons need to be generated for the app. + SkColor icon_color_; + + // The string representation of the icon color. + std::string icon_color_string_; +}; + +// Parses the "app.icon_color" manifest key. +class AppIconColorHandler : public ManifestHandler { + public: + AppIconColorHandler(); + ~AppIconColorHandler() override; + + bool Parse(Extension* extension, base::string16* error) override; + + private: + const std::vector<std::string> Keys() const override; + + DISALLOW_COPY_AND_ASSIGN(AppIconColorHandler); +}; + +} // namespace extensions + +#endif // CHROME_COMMON_EXTENSIONS_MANIFEST_HANDLERS_APP_ICON_COLOR_INFO_H_ diff --git a/chrome/common/web_application_info.cc b/chrome/common/web_application_info.cc index 68a1dbe..5a01d62 100644 --- a/chrome/common/web_application_info.cc +++ b/chrome/common/web_application_info.cc @@ -11,7 +11,8 @@ WebApplicationInfo::IconInfo::~IconInfo() { } WebApplicationInfo::WebApplicationInfo() - : mobile_capable(MOBILE_CAPABLE_UNSPECIFIED) { + : mobile_capable(MOBILE_CAPABLE_UNSPECIFIED), + generated_icon_color(SK_ColorTRANSPARENT) { } WebApplicationInfo::~WebApplicationInfo() { diff --git a/chrome/common/web_application_info.h b/chrome/common/web_application_info.h index 114d53e..b90dbd8 100644 --- a/chrome/common/web_application_info.h +++ b/chrome/common/web_application_info.h @@ -10,6 +10,7 @@ #include "base/strings/string16.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/size.h" #include "url/gurl.h" @@ -49,6 +50,9 @@ struct WebApplicationInfo { // Whether the page is marked as mobile-capable, including apple specific meta // tag. MobileCapable mobile_capable; + + // The color to use if an icon needs to be generated for the web app. + SkColor generated_icon_color; }; #endif // CHROME_COMMON_WEB_APPLICATION_INFO_H_ diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index ee5a09f..4a0fbe6 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn @@ -193,7 +193,6 @@ if (false) { "browser/file_reader_unittest.cc", "browser/guest_view/guest_view_manager_unittest.cc", "browser/image_loader_unittest.cc", - "browser/image_util_unittest.cc", "browser/info_map_unittest.cc", "browser/lazy_background_task_queue_unittest.cc", "browser/management_policy_unittest.cc", @@ -217,6 +216,7 @@ if (false) { "common/extension_resource_unittest.cc", "common/extension_set_unittest.cc", "common/file_util_unittest.cc", + "common/image_util_unittest.cc", "common/manifest_handler_unittest.cc", "common/manifest_handlers/content_capabilities_manifest_unittest.cc", "common/manifest_handlers/oauth2_manifest_unittest.cc", diff --git a/extensions/DEPS b/extensions/DEPS index 1aaa24c..b237be8 100644 --- a/extensions/DEPS +++ b/extensions/DEPS @@ -12,6 +12,7 @@ include_rules = [ "+grit/extensions_renderer_resources.h", "+grit/extensions_resources.h", "+mojo/public", + "+third_party/skia/include", "+testing", # Minimal UI dependencies. There are two good rules for UI dependencies here: diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index ec4c4dd..fee6426 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn @@ -412,8 +412,6 @@ source_set("browser") { "image_loader.h", "image_loader_factory.cc", "image_loader_factory.h", - "image_util.cc", - "image_util.h", "info_map.cc", "info_map.h", "install/crx_installer_error.h", diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS index ca34eba..eb71651 100644 --- a/extensions/browser/DEPS +++ b/extensions/browser/DEPS @@ -19,7 +19,6 @@ include_rules = [ "+sync", "+third_party/leveldatabase", "+third_party/re2", - "+third_party/skia/include", "+third_party/WebKit/public/web", ] diff --git a/extensions/browser/api/app_window/app_window_api.cc b/extensions/browser/api/app_window/app_window_api.cc index e5f23e6..f0a4e83 100644 --- a/extensions/browser/api/app_window/app_window_api.cc +++ b/extensions/browser/api/app_window/app_window_api.cc @@ -21,9 +21,9 @@ #include "extensions/browser/app_window/app_window_registry.h" #include "extensions/browser/app_window/native_app_window.h" #include "extensions/browser/extensions_browser_client.h" -#include "extensions/browser/image_util.h" #include "extensions/common/api/app_window.h" #include "extensions/common/features/simple_feature.h" +#include "extensions/common/image_util.h" #include "extensions/common/manifest.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/switches.h" diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index 54c712f..e25b766 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn @@ -104,6 +104,8 @@ if (enable_extensions) { "file_util.h", "guest_view/guest_view_constants.cc", "guest_view/guest_view_constants.h", + "image_util.cc", + "image_util.h", "install_warning.cc", "install_warning.h", "manifest.cc", diff --git a/extensions/browser/image_util.cc b/extensions/common/image_util.cc index 2454a63..4b16367 100644 --- a/extensions/browser/image_util.cc +++ b/extensions/common/image_util.cc @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "extensions/browser/image_util.h" +#include "extensions/common/image_util.h" #include <stdint.h> #include <vector> #include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" #include "third_party/skia/include/core/SkColor.h" namespace extensions { @@ -41,5 +42,10 @@ bool ParseCSSColorString(const std::string& color_string, SkColor* result) { return true; } +std::string GenerateCSSColorString(SkColor color) { + return base::StringPrintf("#%02X%02X%02X", SkColorGetR(color), + SkColorGetG(color), SkColorGetB(color)); +} + } // namespace image_util } // namespace extensions diff --git a/extensions/browser/image_util.h b/extensions/common/image_util.h index 2886b66..e9d2dfd 100644 --- a/extensions/browser/image_util.h +++ b/extensions/common/image_util.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef EXTENSIONS_BROWSER_IMAGE_UTIL_H_ -#define EXTENSIONS_BROWSER_IMAGE_UTIL_H_ +#ifndef EXTENSIONS_COMMON_IMAGE_UTIL_H_ +#define EXTENSIONS_COMMON_IMAGE_UTIL_H_ #include <string> @@ -16,6 +16,9 @@ namespace image_util { // Parses a string like #FF9982 or #EEE to a color. Returns true for success. bool ParseCSSColorString(const std::string& color_string, SkColor* result); +// Creates a string like #FF9982 from a color. +std::string GenerateCSSColorString(SkColor color); + } // namespace image_util } // namespace extensions diff --git a/extensions/browser/image_util_unittest.cc b/extensions/common/image_util_unittest.cc index 5dd0cee3..ca13ab2 100644 --- a/extensions/browser/image_util_unittest.cc +++ b/extensions/common/image_util_unittest.cc @@ -4,7 +4,7 @@ #include <string> -#include "extensions/browser/image_util.h" +#include "extensions/common/image_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkColor.h" diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc index a7c287a..e8099df 100644 --- a/extensions/common/manifest_constants.cc +++ b/extensions/common/manifest_constants.cc @@ -12,6 +12,7 @@ const char kAboutPage[] = "about_page"; const char kAllFrames[] = "all_frames"; const char kAltKey[] = "altKey"; const char kApp[] = "app"; +const char kAppIconColor[] = "app.icon_color"; const char kAutomation[] = "automation"; const char kBackgroundAllowJsAccess[] = "background.allow_js_access"; const char kBackgroundPage[] = "background.page"; @@ -279,6 +280,7 @@ const char kInvalidAboutPageExpectRelativePath[] = "Invalid value for 'about_page'. Value must be a relative path."; const char kInvalidAllFrames[] = "Invalid value for 'content_scripts[*].all_frames'."; +const char kInvalidAppIconColor[] = "Invalid value for app.icon_color."; const char kInvalidBackground[] = "Invalid value for 'background_page'."; const char kInvalidBackgroundAllowJsAccess[] = diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h index d0e1d88..4c137ce 100644 --- a/extensions/common/manifest_constants.h +++ b/extensions/common/manifest_constants.h @@ -14,6 +14,7 @@ extern const char kAboutPage[]; extern const char kAllFrames[]; extern const char kAltKey[]; extern const char kApp[]; +extern const char kAppIconColor[]; extern const char kAutomation[]; extern const char kBackgroundAllowJsAccess[]; extern const char kBackgroundPage[]; @@ -258,6 +259,7 @@ extern const char kExperimentalFlagRequired[]; extern const char kInvalidAboutPage[]; extern const char kInvalidAboutPageExpectRelativePath[]; extern const char kInvalidAllFrames[]; +extern const char kInvalidAppIconColor[]; extern const char kInvalidBackground[]; extern const char kInvalidBackgroundAllowJsAccess[]; extern const char kInvalidBackgroundCombination[]; diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index e7c350c..f4b6a83 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp @@ -148,6 +148,8 @@ 'common/file_util.h', 'common/guest_view/guest_view_constants.cc', 'common/guest_view/guest_view_constants.h', + 'common/image_util.cc', + 'common/image_util.h', 'common/install_warning.cc', 'common/install_warning.h', 'common/manifest.cc', @@ -692,8 +694,6 @@ 'browser/image_loader.h', 'browser/image_loader_factory.cc', 'browser/image_loader_factory.h', - 'browser/image_util.cc', - 'browser/image_util.h', 'browser/info_map.cc', 'browser/info_map.h', 'browser/install/crx_installer_error.h', @@ -1209,7 +1209,6 @@ 'browser/file_reader_unittest.cc', 'browser/guest_view/guest_view_manager_unittest.cc', 'browser/image_loader_unittest.cc', - 'browser/image_util_unittest.cc', 'browser/info_map_unittest.cc', 'browser/lazy_background_task_queue_unittest.cc', 'browser/management_policy_unittest.cc', @@ -1237,6 +1236,7 @@ 'common/features/complex_feature_unittest.cc', 'common/features/simple_feature_unittest.cc', 'common/file_util_unittest.cc', + 'common/image_util_unittest.cc', 'common/manifest_handler_unittest.cc', 'common/manifest_handlers/content_capabilities_manifest_unittest.cc', 'common/manifest_handlers/default_locale_manifest_unittest.cc', diff --git a/sync/protocol/app_specifics.proto b/sync/protocol/app_specifics.proto index e2f9ef8..a43ea2f 100644 --- a/sync/protocol/app_specifics.proto +++ b/sync/protocol/app_specifics.proto @@ -75,4 +75,8 @@ message AppSpecifics { // This is the description of a bookmark app. optional string bookmark_app_description = 7; + + // This is the color to use when generating bookmark app icons. The string is + // in #rrggbb or #rgb syntax, e.g. #d8d8d8. + optional string bookmark_app_icon_color = 8; } |