diff options
author | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-03 19:58:06 +0000 |
---|---|---|
committer | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-03 19:58:06 +0000 |
commit | bdd6eec2dbd37b2fdc38d32cd69f467bbc2d69cc (patch) | |
tree | e99d5669185f6ac8ccd441baa70b69a65a0331c2 /chrome | |
parent | 04f050b37f95b156b4b60c9e05e5672bc3388f0f (diff) | |
download | chromium_src-bdd6eec2dbd37b2fdc38d32cd69f467bbc2d69cc.zip chromium_src-bdd6eec2dbd37b2fdc38d32cd69f467bbc2d69cc.tar.gz chromium_src-bdd6eec2dbd37b2fdc38d32cd69f467bbc2d69cc.tar.bz2 |
Add support for multiple icon sizes for Mac platform apps
This is the combined version of the following CLs:
http://codereview.chromium.org/9428025/
http://codereview.chromium.org/9500007/
http://codereview.chromium.org/9535002/
BUG=112651
TEST=
Review URL: https://chromiumcodereview.appspot.com/9586018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@124875 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
49 files changed, 539 insertions, 294 deletions
diff --git a/chrome/browser/background/background_application_list_model.cc b/chrome/browser/background/background_application_list_model.cc index 58c815e..dfb4a2d 100644 --- a/chrome/browser/background/background_application_list_model.cc +++ b/chrome/browser/background/background_application_list_model.cc @@ -23,6 +23,7 @@ #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "ui/base/l10n/l10n_util_collator.h" +#include "ui/gfx/image/image.h" class ExtensionNameComparator { public: @@ -55,9 +56,9 @@ class BackgroundApplicationListModel::Application virtual ~Application(); // Invoked when a request icon is available. - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, - int index); + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE; // Uses the FILE thread to request this extension's icon, sized // appropriately. @@ -129,12 +130,12 @@ BackgroundApplicationListModel::Application::Application( } void BackgroundApplicationListModel::Application::OnImageLoaded( - SkBitmap* image, - const ExtensionResource& resource, + const gfx::Image& image, + const std::string& extension_id, int index) { - if (!image) + if (image.IsEmpty()) return; - icon_.reset(new SkBitmap(*image)); + icon_.reset(image.CopySkBitmap()); model_->SendApplicationDataChangedNotifications(extension_); } diff --git a/chrome/browser/extensions/app_shortcut_manager.cc b/chrome/browser/extensions/app_shortcut_manager.cc index e96349a..bec3e3d 100644 --- a/chrome/browser/extensions/app_shortcut_manager.cc +++ b/chrome/browser/extensions/app_shortcut_manager.cc @@ -6,7 +6,6 @@ #include "base/command_line.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/common/chrome_notification_types.h" @@ -15,12 +14,20 @@ #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "grit/theme_resources.h" +#include "skia/ext/image_operations.h" +#include "ui/base/resource/resource_bundle.h" namespace { - // Allow tests to disable shortcut creation, to prevent developers' desktops - // becoming overrun with shortcuts. - bool disable_shortcut_creation_for_tests = false; -} // namespace +// Allow tests to disable shortcut creation, to prevent developers' desktops +// becoming overrun with shortcuts. +bool disable_shortcut_creation_for_tests = false; + +#if defined(OS_MACOSX) +const int kDesiredSizes[] = {16, 32, 128, 256, 512}; +#else +const int kDesiredSizes[] = {32}; +#endif +} // namespace AppShortcutManager::AppShortcutManager(Profile* profile) : profile_(profile), @@ -29,15 +36,23 @@ AppShortcutManager::AppShortcutManager(Profile* profile) content::Source<Profile>(profile_)); } -void AppShortcutManager::OnImageLoaded(SkBitmap *image, - const ExtensionResource &resource, +void AppShortcutManager::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) { // If the image failed to load (e.g. if the resource being loaded was empty) // use the standard application icon. - if (!image || image->isNull()) - image = ExtensionIconSource::LoadImageByResourceId(IDR_APP_DEFAULT_ICON); + if (image.IsEmpty()) { + gfx::Image default_icon = + ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); + int size = kDesiredSizes[arraysize(kDesiredSizes) - 1]; + SkBitmap bmp = skia::ImageOperations::Resize( + *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, + size, size); + shortcut_info_.favicon = gfx::Image(bmp); + } else { + shortcut_info_.favicon = image; + } - shortcut_info_.favicon = *image; web_app::CreateShortcut(profile_->GetPath(), shortcut_info_); } @@ -66,8 +81,6 @@ void AppShortcutManager::InstallApplicationShortcuts( } #endif - const int kAppIconSize = 32; - shortcut_info_.extension_id = extension->id(); shortcut_info_.url = GURL(extension->launch_web_url()); shortcut_info_.title = UTF8ToUTF16(extension->name()); @@ -78,29 +91,36 @@ void AppShortcutManager::InstallApplicationShortcuts( shortcut_info_.create_in_quick_launch_bar = true; shortcut_info_.create_on_desktop = true; - // The icon will be resized to |max_size|. - const gfx::Size max_size(kAppIconSize, kAppIconSize); + std::vector<ImageLoadingTracker::ImageInfo> info_list; + for (size_t i = 0; i < arraysize(kDesiredSizes); ++i) { + int size = kDesiredSizes[i]; + ExtensionResource resource = extension->GetIconResource( + size, ExtensionIconSet::MATCH_EXACTLY); + if (!resource.empty()) { + info_list.push_back( + ImageLoadingTracker::ImageInfo(resource, gfx::Size(size, size))); + } + } - // Look for an icon. If there is no icon at the ideal size, we will resize - // whatever we can get. Making a large icon smaller is prefered to making a - // small icon larger, so look for a larger icon first: - ExtensionResource icon_resource = extension->GetIconResource( - kAppIconSize, - ExtensionIconSet::MATCH_BIGGER); + if (info_list.empty()) { + size_t i = arraysize(kDesiredSizes) - 1; + int size = kDesiredSizes[i]; - // If no icon exists that is the desired size or larger, get the - // largest icon available: - if (icon_resource.empty()) { - icon_resource = extension->GetIconResource( - kAppIconSize, - ExtensionIconSet::MATCH_SMALLER); + // If there is no icon at the desired sizes, we will resize what we can get. + // Making a large icon smaller is prefered to making a small icon larger, so + // look for a larger icon first: + ExtensionResource resource = extension->GetIconResource( + size, ExtensionIconSet::MATCH_BIGGER); + if (resource.empty()) { + resource = extension->GetIconResource( + size, ExtensionIconSet::MATCH_SMALLER); + } + info_list.push_back( + ImageLoadingTracker::ImageInfo(resource, gfx::Size(size, size))); } - // icon_resource may still be empty at this point, in which case LoadImage - // which call the OnImageLoaded callback with a NULL image and exit + // |icon_resources| may still be empty at this point, in which case LoadImage + // will call the OnImageLoaded callback with an empty image and exit // immediately. - tracker_.LoadImage(extension, - icon_resource, - max_size, - ImageLoadingTracker::DONT_CACHE); + tracker_.LoadImages(extension, info_list, ImageLoadingTracker::DONT_CACHE); } diff --git a/chrome/browser/extensions/app_shortcut_manager.h b/chrome/browser/extensions/app_shortcut_manager.h index 7f21f88..d97bbcc2 100644 --- a/chrome/browser/extensions/app_shortcut_manager.h +++ b/chrome/browser/extensions/app_shortcut_manager.h @@ -24,8 +24,8 @@ class AppShortcutManager : public ImageLoadingTracker::Observer, // load the application's icon, which is done when we start creating an // application's shortcuts. This method receives the icon, and completes // the process of installing the shortcuts. - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; // content::NotificationObserver diff --git a/chrome/browser/extensions/extension_icon_manager.cc b/chrome/browser/extensions/extension_icon_manager.cc index 298ab22..e245a7f 100644 --- a/chrome/browser/extensions/extension_icon_manager.cc +++ b/chrome/browser/extensions/extension_icon_manager.cc @@ -15,6 +15,7 @@ #include "ui/gfx/canvas_skia.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/favicon_size.h" +#include "ui/gfx/image/image.h" #include "ui/gfx/size.h" #include "ui/gfx/skbitmap_operations.h" @@ -79,21 +80,19 @@ void ExtensionIconManager::RemoveIcon(const std::string& extension_id) { pending_icons_.erase(extension_id); } -void ExtensionIconManager::OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, +void ExtensionIconManager::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) { - if (!image) + if (image.IsEmpty()) return; - const std::string extension_id = resource.extension_id(); - // We may have removed the icon while waiting for it to load. In that case, // do nothing. if (!ContainsKey(pending_icons_, extension_id)) return; pending_icons_.erase(extension_id); - icons_[extension_id] = ApplyTransforms(*image); + icons_[extension_id] = ApplyTransforms(*image.ToSkBitmap()); } void ExtensionIconManager::EnsureDefaultIcon() { diff --git a/chrome/browser/extensions/extension_icon_manager.h b/chrome/browser/extensions/extension_icon_manager.h index a4a7813..4596d12 100644 --- a/chrome/browser/extensions/extension_icon_manager.h +++ b/chrome/browser/extensions/extension_icon_manager.h @@ -34,7 +34,8 @@ class ExtensionIconManager : public ImageLoadingTracker::Observer { void RemoveIcon(const std::string& extension_id); // Implements the ImageLoadingTracker::Observer interface. - virtual void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; void set_monochrome(bool value) { monochrome_ = value; } diff --git a/chrome/browser/extensions/extension_icon_manager_unittest.cc b/chrome/browser/extensions/extension_icon_manager_unittest.cc index d0401c9..5fb32d7 100644 --- a/chrome/browser/extensions/extension_icon_manager_unittest.cc +++ b/chrome/browser/extensions/extension_icon_manager_unittest.cc @@ -76,9 +76,10 @@ class TestIconManager : public ExtensionIconManager { // Implements the ImageLoadingTracker::Observer interface, and calls through // to the base class' implementation. Then it lets the test know that an // image load was observed. - virtual void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, - int index) { - ExtensionIconManager::OnImageLoaded(image, resource, index); + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE { + ExtensionIconManager::OnImageLoaded(image, extension_id, index); test_->ImageLoadObserved(); } diff --git a/chrome/browser/extensions/extension_install_ui.cc b/chrome/browser/extensions/extension_install_ui.cc index 4587422..8052ecb 100644 --- a/chrome/browser/extensions/extension_install_ui.cc +++ b/chrome/browser/extensions/extension_install_ui.cc @@ -41,6 +41,7 @@ #include "grit/theme_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image.h" using content::WebContents; using extensions::BundleInstaller; @@ -323,7 +324,7 @@ void ExtensionInstallUI::OnInstallFailure(const string16& error) { error); } -void ExtensionInstallUI::SetIcon(SkBitmap* image) { +void ExtensionInstallUI::SetIcon(const SkBitmap* image) { if (image) icon_ = *image; else @@ -332,9 +333,10 @@ void ExtensionInstallUI::SetIcon(SkBitmap* image) { icon_ = Extension::GetDefaultIcon(extension_->is_app()); } -void ExtensionInstallUI::OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) { - SetIcon(image); +void ExtensionInstallUI::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) { + SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap()); switch (prompt_type_) { case PERMISSIONS_PROMPT: diff --git a/chrome/browser/extensions/extension_install_ui.h b/chrome/browser/extensions/extension_install_ui.h index bb3ad1d..9a35da0 100644 --- a/chrome/browser/extensions/extension_install_ui.h +++ b/chrome/browser/extensions/extension_install_ui.h @@ -174,8 +174,9 @@ class ExtensionInstallUI : public ImageLoadingTracker::Observer { virtual void OnInstallFailure(const string16& error); // ImageLoadingTracker::Observer: - virtual void OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) OVERRIDE; + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE; // Opens a new tab page and animates the app icon for the app with id // |app_id|. @@ -201,7 +202,7 @@ class ExtensionInstallUI : public ImageLoadingTracker::Observer { // Sets the icon that will be used in any UI. If |icon| is NULL, or contains // an empty bitmap, then a default icon will be used instead. - void SetIcon(SkBitmap* icon); + void SetIcon(const SkBitmap* icon); // Starts the process of showing a confirmation UI, which is split into two. // 1) Set off a 'load icon' task. diff --git a/chrome/browser/extensions/extension_tab_helper.cc b/chrome/browser/extensions/extension_tab_helper.cc index 6ec0221..e7f1fe9 100644 --- a/chrome/browser/extensions/extension_tab_helper.cc +++ b/chrome/browser/extensions/extension_tab_helper.cc @@ -23,6 +23,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" +#include "ui/gfx/image/image.h" using content::WebContents; @@ -256,11 +257,11 @@ void ExtensionTabHelper::SetAppIcon(const SkBitmap& app_icon) { web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TITLE); } -void ExtensionTabHelper::OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, +void ExtensionTabHelper::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) { - if (image) { - extension_app_icon_ = *image; + if (!image.IsEmpty()) { + extension_app_icon_ = *image.ToSkBitmap(); web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); } } diff --git a/chrome/browser/extensions/extension_tab_helper.h b/chrome/browser/extensions/extension_tab_helper.h index ef1bd99..dd1edc8 100644 --- a/chrome/browser/extensions/extension_tab_helper.h +++ b/chrome/browser/extensions/extension_tab_helper.h @@ -122,7 +122,8 @@ class ExtensionTabHelper void UpdateExtensionAppIcon(const Extension* extension); // ImageLoadingTracker::Observer. - virtual void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; // WebstoreInlineInstaller::Delegate. diff --git a/chrome/browser/extensions/extension_uninstall_dialog.cc b/chrome/browser/extensions/extension_uninstall_dialog.cc index d3044d7..554e929 100644 --- a/chrome/browser/extensions/extension_uninstall_dialog.cc +++ b/chrome/browser/extensions/extension_uninstall_dialog.cc @@ -13,6 +13,7 @@ #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image.h" // Size of extension icon in top left of dialog. static const int kIconSize = 69; @@ -41,12 +42,8 @@ void ExtensionUninstallDialog::ConfirmUninstall(const Extension* extension) { ImageLoadingTracker::DONT_CACHE); } -void ExtensionUninstallDialog::SetIcon(SkBitmap* image) { - if (image) - icon_ = *image; - else - icon_ = SkBitmap(); - if (icon_.empty()) { +void ExtensionUninstallDialog::SetIcon(const gfx::Image& image) { + if (image.IsEmpty()) { if (extension_->is_app()) { icon_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed( IDR_APP_DEFAULT_ICON); @@ -54,11 +51,13 @@ void ExtensionUninstallDialog::SetIcon(SkBitmap* image) { icon_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed( IDR_EXTENSION_DEFAULT_ICON); } + } else { + icon_ = *image.ToSkBitmap(); } } -void ExtensionUninstallDialog::OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, +void ExtensionUninstallDialog::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) { SetIcon(image); diff --git a/chrome/browser/extensions/extension_uninstall_dialog.h b/chrome/browser/extensions/extension_uninstall_dialog.h index a817af3..c0c55ca 100644 --- a/chrome/browser/extensions/extension_uninstall_dialog.h +++ b/chrome/browser/extensions/extension_uninstall_dialog.h @@ -56,13 +56,13 @@ class ExtensionUninstallDialog : public ImageLoadingTracker::Observer { SkBitmap icon_; private: - // Sets the icon that will be used in the dialog. If |icon| is NULL, or - // contains an empty bitmap, then we use a default icon instead. - void SetIcon(SkBitmap* icon); + // Sets the icon that will be used in the dialog. If |icon| contains an empty + // bitmap, then we use a default icon instead. + void SetIcon(const gfx::Image& image); // ImageLoadingTracker::Observer: - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; // Displays the prompt. This should only be called after loading the icon. diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc index a1f48b2..613cb5c 100644 --- a/chrome/browser/extensions/extension_web_ui.cc +++ b/chrome/browser/extensions/extension_web_ui.cc @@ -88,11 +88,13 @@ class ExtensionWebUIImageLoadingTracker : public ImageLoadingTracker::Observer { } } - virtual void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, - int index) { - if (image) { + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE { + if (!image.IsEmpty()) { std::vector<unsigned char> image_data; - if (!gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_data)) { + if (!gfx::PNGCodec::EncodeBGRASkBitmap(*image.ToSkBitmap(), false, + &image_data)) { NOTREACHED() << "Could not encode extension favicon"; } ForwardResult(RefCountedBytes::TakeVector(&image_data)); diff --git a/chrome/browser/extensions/image_loading_tracker.cc b/chrome/browser/extensions/image_loading_tracker.cc index ca60dba..edf1f4b 100644 --- a/chrome/browser/extensions/image_loading_tracker.cc +++ b/chrome/browser/extensions/image_loading_tracker.cc @@ -13,13 +13,39 @@ #include "content/public/browser/notification_service.h" #include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/image/image.h" #include "webkit/glue/image_decoder.h" using content::BrowserThread; +//////////////////////////////////////////////////////////////////////////////// +// ImageLoadingTracker::Observer + ImageLoadingTracker::Observer::~Observer() {} //////////////////////////////////////////////////////////////////////////////// +// ImageLoadingTracker::ImageInfo + +ImageLoadingTracker::ImageInfo::ImageInfo( + const ExtensionResource resource, gfx::Size max_size) + : resource(resource), max_size(max_size) { +} + +ImageLoadingTracker::ImageInfo::~ImageInfo() { +} + +//////////////////////////////////////////////////////////////////////////////// +// ImageLoadingTracker::PendingLoadInfo + +ImageLoadingTracker::PendingLoadInfo::PendingLoadInfo() + : extension(NULL), + pending_count(0) { +} + +ImageLoadingTracker::PendingLoadInfo::~PendingLoadInfo() { +} + +//////////////////////////////////////////////////////////////////////////////// // ImageLoadingTracker::ImageLoader // A RefCounted class for loading images on the File thread and reporting back @@ -102,7 +128,7 @@ class ImageLoadingTracker::ImageLoader DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); if (tracker_) - tracker_->OnImageLoaded(image, resource, original_size, id); + tracker_->OnImageLoaded(image, resource, original_size, id, true); delete image; } @@ -139,46 +165,93 @@ void ImageLoadingTracker::LoadImage(const Extension* extension, const ExtensionResource& resource, const gfx::Size& max_size, CacheParam cache) { - // If we don't have a path we don't need to do any further work, just respond - // back. - int id = next_id_++; - if (resource.relative_path().empty()) { - OnImageLoaded(NULL, resource, max_size, id); - return; - } + std::vector<ImageInfo> info_list; + info_list.push_back(ImageInfo(resource, max_size)); + LoadImages(extension, info_list, cache); +} - DCHECK(extension->path() == resource.extension_root()); +void ImageLoadingTracker::LoadImages(const Extension* extension, + const std::vector<ImageInfo>& info_list, + CacheParam cache) { + PendingLoadInfo load_info; + load_info.extension = extension; + load_info.cache = cache; + load_info.extension_id = extension->id(); + load_info.pending_count = info_list.size(); + int id = next_id_++; + load_map_[id] = load_info; + + for (std::vector<ImageInfo>::const_iterator it = info_list.begin(); + it != info_list.end(); ++it) { + // If we don't have a path we don't need to do any further work, just + // respond back. + if (it->resource.relative_path().empty()) { + OnImageLoaded(NULL, it->resource, it->max_size, id, false); + continue; + } - // See if the extension has the image already. - if (extension->HasCachedImage(resource, max_size)) { - SkBitmap image = extension->GetCachedImage(resource, max_size); - OnImageLoaded(&image, resource, max_size, id); - return; - } + DCHECK(extension->path() == it->resource.extension_root()); - if (cache == CACHE) - load_map_[id] = extension; + // See if the extension has the image already. + if (extension->HasCachedImage(it->resource, it->max_size)) { + SkBitmap image = extension->GetCachedImage(it->resource, it->max_size); + OnImageLoaded(&image, it->resource, it->max_size, id, false); + continue; + } - // Instruct the ImageLoader to load this on the File thread. LoadImage does - // not block. - if (!loader_) - loader_ = new ImageLoader(this); - loader_->LoadImage(resource, max_size, id); + // Instruct the ImageLoader to load this on the File thread. LoadImage does + // not block. + if (!loader_) + loader_ = new ImageLoader(this); + loader_->LoadImage(it->resource, it->max_size, id); + } } void ImageLoadingTracker::OnImageLoaded( SkBitmap* image, const ExtensionResource& resource, const gfx::Size& original_size, - int id) { - LoadMap::iterator i = load_map_.find(id); - if (i != load_map_.end()) { - i->second->SetCachedImage(resource, image ? *image : SkBitmap(), - original_size); - load_map_.erase(i); + int id, + bool should_cache) { + LoadMap::iterator load_map_it = load_map_.find(id); + DCHECK(load_map_it != load_map_.end()); + PendingLoadInfo* info = &load_map_it->second; + + // Save the pending results. + DCHECK(info->pending_count > 0); + info->pending_count--; + if (image) + info->bitmaps.push_back(*image); + + // Add to the extension's image cache if requested. + DCHECK(info->cache != CACHE || info->extension); + if (should_cache && info->cache == CACHE && + !info->extension->HasCachedImage(resource, original_size)) { + info->extension->SetCachedImage(resource, image ? *image : SkBitmap(), + original_size); } - observer_->OnImageLoaded(image, resource, id); + // If all pending images are done then report back. + if (info->pending_count == 0) { + gfx::Image image; + std::string extension_id = info->extension_id; + + if (info->bitmaps.size() > 0) { + std::vector<const SkBitmap*> bitmaps; + for (std::vector<SkBitmap>::const_iterator it = info->bitmaps.begin(); + it != info->bitmaps.end(); ++it) { + // gfx::Image takes ownership of this bitmap. + bitmaps.push_back(new SkBitmap(*it)); + } + image = gfx::Image(bitmaps); + } + + load_map_.erase(load_map_it); + + // ImageLoadingTracker might be deleted after the callback so don't + // anything after this statement. + observer_->OnImageLoaded(image, extension_id, id); + } } void ImageLoadingTracker::Observe(int type, @@ -189,12 +262,13 @@ void ImageLoadingTracker::Observe(int type, const Extension* extension = content::Details<UnloadedExtensionInfo>(details)->extension; - // Remove all entries in the load_map_ referencing the extension. This ensures - // we don't attempt to cache the image when the load completes. - for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end();) { - if (i->second == extension) - load_map_.erase(i++); - else - ++i; + // Remove reference to this extension from all pending load entries. This + // ensures we don't attempt to cache the image when the load completes. + for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end(); ++i) { + PendingLoadInfo* info = &i->second; + if (info->extension == extension) { + info->extension = NULL; + info->cache = DONT_CACHE; + } } } diff --git a/chrome/browser/extensions/image_loading_tracker.h b/chrome/browser/extensions/image_loading_tracker.h index e59371d..6363877 100644 --- a/chrome/browser/extensions/image_loading_tracker.h +++ b/chrome/browser/extensions/image_loading_tracker.h @@ -10,15 +10,16 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" +#include "chrome/common/extensions/extension_resource.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "ui/gfx/size.h" class Extension; -class ExtensionResource; class SkBitmap; namespace gfx { - class Size; +class Image; } // The views need to load their icons asynchronously but might be deleted before @@ -46,20 +47,28 @@ class ImageLoadingTracker : public content::NotificationObserver { class Observer { public: // Will be called when the image with the given index has loaded. - // The |image| is owned by the tracker, so the observer should make a copy - // if they need to access it after this call. |image| can be null if a valid - // image was not found or it failed to decode. |resource| is the - // ExtensionResource where the |image| came from and the |index| represents - // the index of the image just loaded (starts at 0 and increments every - // time LoadImage is called). - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + // |image| can be empty if a valid image was not found or it failed to + // decode. |extension_id| is the ID of the extension the images are loaded + // from. |index| represents the index of the image just loaded (starts at 0 + // and increments every time LoadImage is called). + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) = 0; protected: virtual ~Observer(); }; + // Information about a single image to load from a extension resource. + struct ImageInfo { + ImageInfo(const ExtensionResource resource, gfx::Size max_size); + ~ImageInfo(); + ExtensionResource resource; + // If the loaded image is larger than |max_size| it will be resized to those + // dimensions. + gfx::Size max_size; + }; + explicit ImageLoadingTracker(Observer* observer); virtual ~ImageLoadingTracker(); @@ -72,13 +81,35 @@ class ImageLoadingTracker : public content::NotificationObserver { const gfx::Size& max_size, CacheParam cache); + // Same as LoadImage() above except it loads multiple images from the same + // extension. This is used to load multiple resolutions of the same image + // type. + void LoadImages(const Extension* extension, + const std::vector<ImageInfo>& info_list, + CacheParam cache); + // Returns the ID used for the next image that is loaded. That is, the return // value from this method corresponds to the int that is passed to // OnImageLoaded() the next time LoadImage() is invoked. int next_id() const { return next_id_; } private: - typedef std::map<int, const Extension*> LoadMap; + // Information for pending image load operation for one or more images. + struct PendingLoadInfo { + PendingLoadInfo(); + ~PendingLoadInfo(); + + const Extension* extension; + // This is cached separate from |extension| in case the extension in + // unloaded. + std::string extension_id; + CacheParam cache; + size_t pending_count; + std::vector<SkBitmap> bitmaps; + }; + + // Maps an integer identifying a load request to a PendingLoadInfo. + typedef std::map<int, PendingLoadInfo> LoadMap; class ImageLoader; @@ -89,7 +120,7 @@ class ImageLoadingTracker : public content::NotificationObserver { // of the image before any resizing was done. // |image| may be null if the file failed to decode. void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, - const gfx::Size& original_size, int id); + const gfx::Size& original_size, int id, bool should_cache); // content::NotificationObserver method. If an extension is uninstalled while // we're waiting for the image we remove the entry from load_map_. @@ -106,9 +137,8 @@ class ImageLoadingTracker : public content::NotificationObserver { // The object responsible for loading the image on the File thread. scoped_refptr<ImageLoader> loader_; - // If LoadImage is told to cache the result an entry is added here. The - // integer identifies the id assigned to the request. If the extension is - // deleted while fetching the image the entry is removed from the map. + // Information for each LoadImage request is cached here. The integer + // identifies the id assigned to the request. LoadMap load_map_; content::NotificationRegistrar registrar_; diff --git a/chrome/browser/extensions/image_loading_tracker_unittest.cc b/chrome/browser/extensions/image_loading_tracker_unittest.cc index 3f4983e..67be34f 100644 --- a/chrome/browser/extensions/image_loading_tracker_unittest.cc +++ b/chrome/browser/extensions/image_loading_tracker_unittest.cc @@ -15,6 +15,7 @@ #include "content/test/test_browser_thread.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/image/image.h" #include "ui/gfx/size.h" using content::BrowserThread; @@ -30,15 +31,13 @@ class ImageLoadingTrackerTest : public testing::Test, io_thread_(BrowserThread::IO) { } - virtual void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, - int index) { + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE { image_loaded_count_++; if (quit_in_image_loaded_) MessageLoop::current()->Quit(); - if (image) - image_ = *image; - else - image_.reset(); + image_ = image; } void WaitForImageLoad() { @@ -80,7 +79,7 @@ class ImageLoadingTrackerTest : public testing::Test, Extension::STRICT_ERROR_CHECKS, &error); } - SkBitmap image_; + gfx::Image image_; private: virtual void SetUp() { @@ -106,7 +105,7 @@ TEST_F(ImageLoadingTrackerTest, Cache) { ExtensionIconSet::MATCH_EXACTLY); gfx::Size max_size(ExtensionIconSet::EXTENSION_ICON_SMALLISH, ExtensionIconSet::EXTENSION_ICON_SMALLISH); - ImageLoadingTracker loader(static_cast<ImageLoadingTracker::Observer*>(this)); + ImageLoadingTracker loader(this); loader.LoadImage(extension.get(), image_resource, max_size, @@ -121,7 +120,8 @@ TEST_F(ImageLoadingTrackerTest, Cache) { EXPECT_EQ(1, image_loaded_count()); // Check that the image was loaded. - EXPECT_EQ(ExtensionIconSet::EXTENSION_ICON_SMALLISH, image_.width()); + EXPECT_EQ(ExtensionIconSet::EXTENSION_ICON_SMALLISH, + image_.ToSkBitmap()->width()); // The image should be cached in the Extension. EXPECT_TRUE(extension->HasCachedImage(image_resource, max_size)); @@ -139,7 +139,8 @@ TEST_F(ImageLoadingTrackerTest, Cache) { EXPECT_EQ(1, image_loaded_count()); // Check that the image was loaded. - EXPECT_EQ(ExtensionIconSet::EXTENSION_ICON_SMALLISH, image_.width()); + EXPECT_EQ(ExtensionIconSet::EXTENSION_ICON_SMALLISH, + image_.ToSkBitmap()->width()); } // Tests deleting an extension while waiting for the image to load doesn't cause @@ -151,7 +152,7 @@ TEST_F(ImageLoadingTrackerTest, DeleteExtensionWhileWaitingForCache) { ExtensionResource image_resource = extension->GetIconResource(ExtensionIconSet::EXTENSION_ICON_SMALLISH, ExtensionIconSet::MATCH_EXACTLY); - ImageLoadingTracker loader(static_cast<ImageLoadingTracker::Observer*>(this)); + ImageLoadingTracker loader(this); loader.LoadImage(extension.get(), image_resource, gfx::Size(ExtensionIconSet::EXTENSION_ICON_SMALLISH, @@ -180,5 +181,43 @@ TEST_F(ImageLoadingTrackerTest, DeleteExtensionWhileWaitingForCache) { EXPECT_EQ(1, image_loaded_count()); // Check that the image was loaded. - EXPECT_EQ(ExtensionIconSet::EXTENSION_ICON_SMALLISH, image_.width()); + EXPECT_EQ(ExtensionIconSet::EXTENSION_ICON_SMALLISH, + image_.ToSkBitmap()->width()); +} + +// Tests loading multiple dimensions of the same image. +TEST_F(ImageLoadingTrackerTest, MultipleImages) { + scoped_refptr<Extension> extension(CreateExtension()); + ASSERT_TRUE(extension.get() != NULL); + + std::vector<ImageLoadingTracker::ImageInfo> info_list; + int sizes[] = {ExtensionIconSet::EXTENSION_ICON_SMALLISH, + ExtensionIconSet::EXTENSION_ICON_BITTY}; + for (size_t i = 0; i < arraysize(sizes); ++i) { + ExtensionResource resource = + extension->GetIconResource(sizes[i], ExtensionIconSet::MATCH_EXACTLY); + info_list.push_back(ImageLoadingTracker::ImageInfo( + resource, gfx::Size(sizes[i], sizes[i]))); + } + + ImageLoadingTracker loader(this); + loader.LoadImages(extension.get(), info_list, ImageLoadingTracker::CACHE); + + // The image isn't cached, so we should not have received notification. + EXPECT_EQ(0, image_loaded_count()); + + WaitForImageLoad(); + + // We should have gotten the image. + EXPECT_EQ(1, image_loaded_count()); + + // Check that all images were loaded. + ASSERT_EQ(2u, image_.GetNumberOfSkBitmaps()); + const SkBitmap* bmp1 = image_.GetSkBitmapAtIndex(0); + const SkBitmap* bmp2 = image_.GetSkBitmapAtIndex(1); + if (bmp1->width() > bmp2->width()) { + std::swap(bmp1, bmp2); + } + EXPECT_EQ(ExtensionIconSet::EXTENSION_ICON_BITTY, bmp1->width()); + EXPECT_EQ(ExtensionIconSet::EXTENSION_ICON_SMALLISH, bmp2->width()); } diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h index 21ee71f..8083b6a 100644 --- a/chrome/browser/shell_integration.h +++ b/chrome/browser/shell_integration.h @@ -14,6 +14,7 @@ #include "base/string16.h" #include "googleurl/src/gurl.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/image/image.h" class CommandLine; @@ -77,7 +78,7 @@ class ShellIntegration { string16 title; string16 description; FilePath extension_path; - SkBitmap favicon; + gfx::Image favicon; // Shortcuts to platform apps are created differently. They start up with // their own user data directory and load the app from |extension_path|. diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc index 574bd09..d351c35 100644 --- a/chrome/browser/shell_integration_linux.cc +++ b/chrome/browser/shell_integration_linux.cc @@ -73,7 +73,7 @@ bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code) { std::string CreateShortcutIcon( const ShellIntegration::ShortcutInfo& shortcut_info, const FilePath& shortcut_filename) { - if (shortcut_info.favicon.isNull()) + if (shortcut_info.favicon.IsEmpty()) return std::string(); // TODO(phajdan.jr): Report errors from this function, possibly as infobars. @@ -85,7 +85,8 @@ std::string CreateShortcutIcon( shortcut_filename.ReplaceExtension("png")); std::vector<unsigned char> png_data; - gfx::PNGCodec::EncodeBGRASkBitmap(shortcut_info.favicon, false, &png_data); + const SkBitmap* bitmap = shortcut_info.favicon.ToSkBitmap(); + gfx::PNGCodec::EncodeBGRASkBitmap(*bitmap, false, &png_data); int bytes_written = file_util::WriteFile(temp_file_path, reinterpret_cast<char*>(png_data.data()), png_data.size()); @@ -102,7 +103,7 @@ std::string CreateShortcutIcon( argv.push_back("user"); argv.push_back("--size"); - argv.push_back(base::IntToString(shortcut_info.favicon.width())); + argv.push_back(base::IntToString(bitmap->width())); argv.push_back(temp_file_path.value()); std::string icon_name = temp_file_path.BaseName().RemoveExtension().value(); diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm index 836262e..f90ae1d 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm @@ -22,6 +22,7 @@ #include "skia/ext/skia_utils_mac.h" #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" #include "ui/gfx/canvas_skia_paint.h" +#include "ui/gfx/image/image.h" #include "ui/gfx/rect.h" #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" #include "ui/gfx/size.h" @@ -66,10 +67,11 @@ class ExtensionImageTrackerBridge : public content::NotificationObserver, ~ExtensionImageTrackerBridge() {} // ImageLoadingTracker::Observer implementation. - void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, - int index) { - if (image) - [owner_ setDefaultIcon:gfx::SkBitmapToNSImage(*image)]; + void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE { + if (!image.IsEmpty()) + [owner_ setDefaultIcon:image.ToNSImage()]; [owner_ updateState]; } diff --git a/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.mm b/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.mm index f3353ec..7718e46 100644 --- a/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.mm +++ b/chrome/browser/ui/cocoa/infobars/extension_infobar_controller.mm @@ -23,6 +23,7 @@ #include "skia/ext/skia_utils_mac.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas_skia.h" +#include "ui/gfx/image/image.h" namespace { const CGFloat kAnimationDuration = 0.12; @@ -72,32 +73,29 @@ class InfobarBridge : public ExtensionInfoBarDelegate::DelegateObserver, ExtensionResource icon_resource = extension->GetIconResource(ExtensionIconSet::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_EXACTLY); - if (!icon_resource.relative_path().empty()) { - tracker_.LoadImage(extension, icon_resource, - gfx::Size(ExtensionIconSet::EXTENSION_ICON_BITTY, - ExtensionIconSet::EXTENSION_ICON_BITTY), - ImageLoadingTracker::DONT_CACHE); - } else { - OnImageLoaded(NULL, icon_resource, 0); - } + tracker_.LoadImage(extension, icon_resource, + gfx::Size(ExtensionIconSet::EXTENSION_ICON_BITTY, + ExtensionIconSet::EXTENSION_ICON_BITTY), + ImageLoadingTracker::DONT_CACHE); } // ImageLoadingTracker::Observer implementation. // TODO(andybons): The infobar view implementations share a lot of the same // code. Come up with a strategy to share amongst them. - virtual void OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) { + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE { if (!delegate_) return; // The delegate can go away while the image asynchronously loads. ResourceBundle& rb = ResourceBundle::GetSharedInstance(); // Fall back on the default extension icon on failure. - SkBitmap* icon; - if (!image || image->empty()) + const SkBitmap* icon; + if (image.IsEmpty()) icon = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION); else - icon = image; + icon = image.ToSkBitmap(); SkBitmap* drop_image = rb.GetBitmapNamed(IDR_APP_DROPARROW); diff --git a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h index 52b019f..0894c5a 100644 --- a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h +++ b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h @@ -37,8 +37,9 @@ class PageActionDecoration : public ImageDecoration, bool preview_enabled() const { return preview_enabled_; } // Overridden from |ImageLoadingTracker::Observer|. - virtual void OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) OVERRIDE; + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE; // Called to notify the Page Action that it should determine whether // to be visible or hidden. |contents| is the WebContents that is diff --git a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm index 39467d9..29a1bcf 100644 --- a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm +++ b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm @@ -114,8 +114,9 @@ bool PageActionDecoration::OnMousePressed(NSRect frame) { return true; } -void PageActionDecoration::OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) { +void PageActionDecoration::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) { // We loaded icons()->size() icons, plus one extra if the Page Action had // a default icon. int total_icons = static_cast<int>(page_action_->icon_paths()->size()); @@ -125,11 +126,12 @@ void PageActionDecoration::OnImageLoaded( // Map the index of the loaded image back to its name. If we ever get an // index greater than the number of icons, it must be the default icon. - if (image) { + if (!image.IsEmpty()) { + const SkBitmap* bitmap = image.ToSkBitmap(); if (index < static_cast<int>(page_action_->icon_paths()->size())) - page_action_icons_[page_action_->icon_paths()->at(index)] = *image; + page_action_icons_[page_action_->icon_paths()->at(index)] = *bitmap; else - page_action_icons_[page_action_->default_icon_path()] = *image; + page_action_icons_[page_action_->default_icon_path()] = *bitmap; } // If we have no owner, that means this class is still being constructed and diff --git a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc index 31548aa..3c8f616 100644 --- a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc +++ b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc @@ -39,6 +39,7 @@ #include "ui/base/gtk/gtk_compat.h" #include "ui/gfx/canvas_skia_paint.h" #include "ui/gfx/gtk_util.h" +#include "ui/gfx/image/image.h" namespace { @@ -160,11 +161,13 @@ class BrowserActionButton : public content::NotificationObserver, } // ImageLoadingTracker::Observer implementation. - void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, - int index) { - if (image) { - default_skbitmap_ = *image; - default_icon_ = gfx::GdkPixbufFromSkBitmap(image); + void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE { + if (!image.IsEmpty()) { + default_skbitmap_ = *image.ToSkBitmap(); + default_icon_ = + static_cast<GdkPixbuf*>(g_object_ref(image.ToGdkPixbuf())); } UpdateState(); } diff --git a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc index 92c8bfa..cac3d5a 100644 --- a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc +++ b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc @@ -25,6 +25,7 @@ #include "grit/theme_resources.h" #include "ui/base/gtk/gtk_hig_constants.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" #include "ui/gfx/gtk_util.h" using content::BrowserThread; @@ -66,10 +67,11 @@ CreateApplicationShortcutsDialogGtk::CreateApplicationShortcutsDialogGtk( } void CreateApplicationShortcutsDialogGtk::CreateIconPixBuf( - const SkBitmap& bitmap) { + const gfx::Image& image) { // Prepare the icon. Try to scale it if it's too small, otherwise it would // look weird. - GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&shortcut_info_.favicon); + GdkPixbuf* pixbuf = + static_cast<GdkPixbuf*>(g_object_ref(image.ToGdkPixbuf())); int pixbuf_width = gdk_pixbuf_get_width(pixbuf); int pixbuf_height = gdk_pixbuf_get_height(pixbuf); if (pixbuf_width == pixbuf_height && pixbuf_width < kIconPreviewSizePixels) { @@ -332,12 +334,16 @@ CreateChromeApplicationShortcutsDialogGtk:: // Called by tracker_ when the app's icon is loaded. void CreateChromeApplicationShortcutsDialogGtk::OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) { - if (!image || image->isNull()) - image = ExtensionIconSource::LoadImageByResourceId(IDR_APP_DEFAULT_ICON); - - shortcut_info_.favicon = *image; + const gfx::Image& image, + const std::string& extension_id, + int index) { + if (image.IsEmpty()) { + shortcut_info_.favicon = + ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); + } else { + shortcut_info_.favicon = image; + } - CreateIconPixBuf(*image); + CreateIconPixBuf(shortcut_info_.favicon); CreateDialogBox(parent_); } diff --git a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h index 200f661..2bfeb27 100644 --- a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h +++ b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h @@ -43,7 +43,7 @@ class CreateApplicationShortcutsDialogGtk OnToggleCheckbox); virtual void CreateDialogBox(GtkWindow* parent); - virtual void CreateIconPixBuf(const SkBitmap& bitmap); + virtual void CreateIconPixBuf(const gfx::Image& image); // This method is called after a shortcut is created. // Subclasses can override it to take some action at that time. @@ -111,8 +111,8 @@ class CreateChromeApplicationShortcutsDialogGtk // Implement ImageLoadingTracker::Observer. |tracker_| is used to // load the app's icon. This method recieves the icon, and adds // it to the "Create Shortcut" dailog box. - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; private: diff --git a/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.cc b/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.cc index 4251b18..3706ea19 100644 --- a/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.cc +++ b/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.cc @@ -63,17 +63,20 @@ void ExtensionInfoBarGtk::GetBottomColor(InfoBarDelegate::Type type, *r = *g = *b = 218.0 / 255.0; } -void ExtensionInfoBarGtk::OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) { +void ExtensionInfoBarGtk::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) { if (!delegate_) return; // The delegate can go away while we asynchronously load images. // TODO(erg): IDR_EXTENSIONS_SECTION should have an IDR_INFOBAR_EXTENSIONS // icon of the correct size with real subpixel shading and such. - SkBitmap* icon = image; + const SkBitmap* icon = NULL; ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - if (!image || image->empty()) + if (image.IsEmpty()) icon = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION); + else + icon = image.ToSkBitmap(); SkBitmap* drop_image = rb.GetBitmapNamed(IDR_APP_DROPARROW); @@ -110,15 +113,11 @@ void ExtensionInfoBarGtk::BuildWidgets() { const Extension* extension = delegate_->extension_host()->extension(); ExtensionResource icon_resource = extension->GetIconResource( ExtensionIconSet::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_EXACTLY); - if (!icon_resource.relative_path().empty()) { - // Create a tracker to load the image. It will report back on OnImageLoaded. - tracker_.LoadImage(extension, icon_resource, - gfx::Size(ExtensionIconSet::EXTENSION_ICON_BITTY, - ExtensionIconSet::EXTENSION_ICON_BITTY), - ImageLoadingTracker::DONT_CACHE); - } else { - OnImageLoaded(NULL, icon_resource, 0); - } + // Create a tracker to load the image. It will report back on OnImageLoaded. + tracker_.LoadImage(extension, icon_resource, + gfx::Size(ExtensionIconSet::EXTENSION_ICON_BITTY, + ExtensionIconSet::EXTENSION_ICON_BITTY), + ImageLoadingTracker::DONT_CACHE); // Pad the bottom of the infobar by one pixel for the border. alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); diff --git a/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.h b/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.h index fd8e7bc..8dc2c9a 100644 --- a/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.h +++ b/chrome/browser/ui/gtk/infobars/extension_infobar_gtk.h @@ -36,8 +36,9 @@ class ExtensionInfoBarGtk : public InfoBarGtk, double* r, double* g, double* b) OVERRIDE; // Overridden from ImageLoadingTracker::Observer: - virtual void OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) OVERRIDE; + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE; // Overridden from MenuGtk::Delegate: virtual void StoppedShowing() OVERRIDE; diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.cc b/chrome/browser/ui/gtk/location_bar_view_gtk.cc index 9f95955..9e8712d 100644 --- a/chrome/browser/ui/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/ui/gtk/location_bar_view_gtk.cc @@ -1556,7 +1556,9 @@ void LocationBarViewGtk::PageActionViewGtk::UpdateVisibility( } void LocationBarViewGtk::PageActionViewGtk::OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) { + const gfx::Image& image, + const std::string& extension_id, + int index) { // We loaded icons()->size() icons, plus one extra if the page action had // a default icon. int total_icons = static_cast<int>(page_action_->icon_paths()->size()); @@ -1566,8 +1568,9 @@ void LocationBarViewGtk::PageActionViewGtk::OnImageLoaded( // Map the index of the loaded image back to its name. If we ever get an // index greater than the number of icons, it must be the default icon. - if (image) { - GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(image); + if (!image.IsEmpty()) { + GdkPixbuf* pixbuf = + static_cast<GdkPixbuf*>(g_object_ref(image.ToGdkPixbuf())); if (index < static_cast<int>(page_action_->icon_paths()->size())) pixbufs_[page_action_->icon_paths()->at(index)] = pixbuf; else diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.h b/chrome/browser/ui/gtk/location_bar_view_gtk.h index eae6264..3abccb2 100644 --- a/chrome/browser/ui/gtk/location_bar_view_gtk.h +++ b/chrome/browser/ui/gtk/location_bar_view_gtk.h @@ -228,8 +228,9 @@ class LocationBarViewGtk : public AutocompleteEditController, void UpdateVisibility(content::WebContents* contents, const GURL& url); // A callback from ImageLoadingTracker for when the image has loaded. - virtual void OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) OVERRIDE; + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE; // Simulate left mouse click on the page action button. void TestActivatePageAction(); diff --git a/chrome/browser/ui/views/ash/app_list/extension_app_item.cc b/chrome/browser/ui/views/ash/app_list/extension_app_item.cc index f796e80..2e815e1 100644 --- a/chrome/browser/ui/views/ash/app_list/extension_app_item.cc +++ b/chrome/browser/ui/views/ash/app_list/extension_app_item.cc @@ -137,11 +137,11 @@ void ExtensionAppItem::LoadDefaultImage() { SetIcon(*rb.GetImageNamed(resource).ToSkBitmap()); } -void ExtensionAppItem::OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, +void ExtensionAppItem::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int tracker_index) { - if (image && !image->empty()) - SetIcon(*image); + if (!image.IsEmpty()) + SetIcon(*image.ToSkBitmap()); else LoadDefaultImage(); } diff --git a/chrome/browser/ui/views/ash/app_list/extension_app_item.h b/chrome/browser/ui/views/ash/app_list/extension_app_item.h index a1a56d6..c8aca90 100644 --- a/chrome/browser/ui/views/ash/app_list/extension_app_item.h +++ b/chrome/browser/ui/views/ash/app_list/extension_app_item.h @@ -43,8 +43,8 @@ class ExtensionAppItem : public ChromeAppListItem, void LoadDefaultImage(); // Overridden from ImageLoadingTracker::Observer - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int tracker_index) OVERRIDE; // Overridden from ChromeAppListItem: diff --git a/chrome/browser/ui/views/ash/launcher/chrome_launcher_delegate.cc b/chrome/browser/ui/views/ash/launcher/chrome_launcher_delegate.cc index 920bde6..a528729 100644 --- a/chrome/browser/ui/views/ash/launcher/chrome_launcher_delegate.cc +++ b/chrome/browser/ui/views/ash/launcher/chrome_launcher_delegate.cc @@ -351,7 +351,7 @@ std::string ChromeLauncherDelegate::GetAppID(TabContentsWrapper* tab) { } void ChromeLauncherDelegate::SetAppImage(const std::string& id, - SkBitmap* image) { + const SkBitmap* image) { for (IDToItemMap::const_iterator i = id_to_item_map_.begin(); i != id_to_item_map_.end(); ++i) { if (i->second.app_id == id) { diff --git a/chrome/browser/ui/views/ash/launcher/chrome_launcher_delegate.h b/chrome/browser/ui/views/ash/launcher/chrome_launcher_delegate.h index aa9f360..160cb16 100644 --- a/chrome/browser/ui/views/ash/launcher/chrome_launcher_delegate.h +++ b/chrome/browser/ui/views/ash/launcher/chrome_launcher_delegate.h @@ -135,7 +135,7 @@ class ChromeLauncherDelegate : public ash::LauncherDelegate, // Sets the image for an app tab. This is intended to be invoked from the // AppIconLoader. - void SetAppImage(const std::string& app_id, SkBitmap* image); + void SetAppImage(const std::string& app_id, const SkBitmap* image); ash::LauncherModel* model() { return model_; } diff --git a/chrome/browser/ui/views/ash/launcher/launcher_icon_loader.cc b/chrome/browser/ui/views/ash/launcher/launcher_icon_loader.cc index 3f3963d..45fd8d6 100644 --- a/chrome/browser/ui/views/ash/launcher/launcher_icon_loader.cc +++ b/chrome/browser/ui/views/ash/launcher/launcher_icon_loader.cc @@ -51,8 +51,8 @@ void LauncherIconLoader::FetchImage(const std::string& id) { ImageLoadingTracker::CACHE); } -void LauncherIconLoader::OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, +void LauncherIconLoader::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) { ImageLoaderIDToExtensionIDMap::iterator i = map_.find(index); if (i == map_.end()) @@ -60,7 +60,10 @@ void LauncherIconLoader::OnImageLoaded(SkBitmap* image, std::string id = i->second; map_.erase(i); - host_->SetAppImage(id, image); + if (image.IsEmpty()) + host_->SetAppImage(id, NULL); + else + host_->SetAppImage(id, image.ToSkBitmap()); } const Extension* LauncherIconLoader::GetExtensionForTab( diff --git a/chrome/browser/ui/views/ash/launcher/launcher_icon_loader.h b/chrome/browser/ui/views/ash/launcher/launcher_icon_loader.h index d26d53a..d4f763a 100644 --- a/chrome/browser/ui/views/ash/launcher/launcher_icon_loader.h +++ b/chrome/browser/ui/views/ash/launcher/launcher_icon_loader.h @@ -30,8 +30,8 @@ class LauncherIconLoader : public ChromeLauncherDelegate::AppIconLoader, virtual void FetchImage(const std::string& id) OVERRIDE; // ImageLoadingTracker::Observer: - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; private: diff --git a/chrome/browser/ui/views/browser_actions_container.cc b/chrome/browser/ui/views/browser_actions_container.cc index ef3dd6e..b86dc14 100644 --- a/chrome/browser/ui/views/browser_actions_container.cc +++ b/chrome/browser/ui/views/browser_actions_container.cc @@ -136,11 +136,11 @@ void BrowserActionButton::ButtonPressed(views::Button* sender, panel_->OnBrowserActionExecuted(this, false); } -void BrowserActionButton::OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, +void BrowserActionButton::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) { - if (image) - default_icon_ = *image; + if (!image.IsEmpty()) + default_icon_ = *image.ToSkBitmap(); // Call back to UpdateState() because a more specific icon might have been set // while the load was outstanding. diff --git a/chrome/browser/ui/views/browser_actions_container.h b/chrome/browser/ui/views/browser_actions_container.h index cb20e3a..14a2582 100644 --- a/chrome/browser/ui/views/browser_actions_container.h +++ b/chrome/browser/ui/views/browser_actions_container.h @@ -84,8 +84,8 @@ class BrowserActionButton : public views::MenuButton, const views::Event& event) OVERRIDE; // Overridden from ImageLoadingTracker. - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; // Overridden from content::NotificationObserver: diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc index 515d462..7caf2ea 100644 --- a/chrome/browser/ui/views/create_application_shortcut_view.cc +++ b/chrome/browser/ui/views/create_application_shortcut_view.cc @@ -57,7 +57,7 @@ class AppInfoView : public views::View { void UpdateText(const string16& title, const string16& description); // Updates the icon of the web app. - void UpdateIcon(const SkBitmap& new_icon); + void UpdateIcon(const gfx::Image& image); // Overridden from views::View: virtual void OnPaint(gfx::Canvas* canvas); @@ -159,8 +159,9 @@ void AppInfoView::UpdateText(const string16& title, SetupLayout(); } -void AppInfoView::UpdateIcon(const SkBitmap& new_icon) { - icon_->SetImage(new_icon); +void AppInfoView::UpdateIcon(const gfx::Image& image) { + if (!image.IsEmpty()) + icon_->SetImage(image.ToSkBitmap()); } void AppInfoView::OnPaint(gfx::Canvas* canvas) { @@ -469,7 +470,7 @@ void CreateUrlApplicationShortcutView::OnIconDownloaded(bool errored, pending_download_ = NULL; if (!errored && !image.isNull()) { - shortcut_info_.favicon = image; + shortcut_info_.favicon = gfx::Image(image); static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_.favicon); } else { FetchIcon(); @@ -524,11 +525,16 @@ CreateChromeApplicationShortcutView::~CreateChromeApplicationShortcutView() {} // Called by tracker_ when the app's icon is loaded. void CreateChromeApplicationShortcutView::OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) { - if (!image || image->isNull()) - image = ExtensionIconSource::LoadImageByResourceId(IDR_APP_DEFAULT_ICON); + const gfx::Image& image, + const std::string& extension_id, + int index) { + if (image.IsEmpty()) { + shortcut_info_.favicon = ui::ResourceBundle::GetSharedInstance(). + GetImageNamed(IDR_APP_DEFAULT_ICON); + } else { + shortcut_info_.favicon = image; + } - shortcut_info_.favicon = *image; CHECK(app_info_); static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_.favicon); } diff --git a/chrome/browser/ui/views/create_application_shortcut_view.h b/chrome/browser/ui/views/create_application_shortcut_view.h index 0602628..8a49f9b 100644 --- a/chrome/browser/ui/views/create_application_shortcut_view.h +++ b/chrome/browser/ui/views/create_application_shortcut_view.h @@ -116,8 +116,8 @@ class CreateChromeApplicationShortcutView // Implement ImageLoadingTracker::Observer. |tracker_| is used to // load the app's icon. This method recieves the icon, and adds // it to the "Create Shortcut" dailog box. - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; private: diff --git a/chrome/browser/ui/views/infobars/extension_infobar.cc b/chrome/browser/ui/views/infobars/extension_infobar.cc index db272a9..1e47b89 100644 --- a/chrome/browser/ui/views/infobars/extension_infobar.cc +++ b/chrome/browser/ui/views/infobars/extension_infobar.cc @@ -16,6 +16,7 @@ #include "ui/base/animation/slide_animation.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas_skia.h" +#include "ui/gfx/image/image.h" #include "ui/views/controls/button/menu_button.h" #include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/widget/widget.h" @@ -93,29 +94,27 @@ void ExtensionInfoBar::ViewHierarchyChanged(bool is_add, ExtensionIconSet::Icons image_size = ExtensionIconSet::EXTENSION_ICON_BITTY; ExtensionResource icon_resource = extension->GetIconResource( image_size, ExtensionIconSet::MATCH_EXACTLY); - if (!icon_resource.relative_path().empty()) { - tracker_.LoadImage(extension, icon_resource, - gfx::Size(image_size, image_size), ImageLoadingTracker::DONT_CACHE); - } else { - OnImageLoaded(NULL, icon_resource, 0); - } + tracker_.LoadImage(extension, icon_resource, + gfx::Size(image_size, image_size), ImageLoadingTracker::DONT_CACHE); } int ExtensionInfoBar::ContentMinimumWidth() const { return menu_->GetPreferredSize().width() + kMenuHorizontalMargin; } -void ExtensionInfoBar::OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, +void ExtensionInfoBar::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) { if (!GetDelegate()) return; // The delegate can go away while we asynchronously load images. - SkBitmap* icon = image; + const SkBitmap* icon = NULL; // Fall back on the default extension icon on failure. ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - if (!image || image->empty()) + if (image.IsEmpty()) icon = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION); + else + icon = image.ToSkBitmap(); SkBitmap* drop_image = rb.GetBitmapNamed(IDR_APP_DROPARROW); diff --git a/chrome/browser/ui/views/infobars/extension_infobar.h b/chrome/browser/ui/views/infobars/extension_infobar.h index 07d347a..dc9b0c6 100644 --- a/chrome/browser/ui/views/infobars/extension_infobar.h +++ b/chrome/browser/ui/views/infobars/extension_infobar.h @@ -37,8 +37,8 @@ class ExtensionInfoBar : public InfoBarView, virtual int ContentMinimumWidth() const OVERRIDE; // ImageLoadingTracker::Observer: - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; // ExtensionInfoBarDelegate::DelegateObserver: diff --git a/chrome/browser/ui/views/location_bar/page_action_image_view.cc b/chrome/browser/ui/views/location_bar/page_action_image_view.cc index ed0f8f6..f275df8 100644 --- a/chrome/browser/ui/views/location_bar/page_action_image_view.cc +++ b/chrome/browser/ui/views/location_bar/page_action_image_view.cc @@ -177,8 +177,9 @@ void PageActionImageView::ShowContextMenu(const gfx::Point& p, return; } -void PageActionImageView::OnImageLoaded( - SkBitmap* image, const ExtensionResource& resource, int index) { +void PageActionImageView::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) { // We loaded icons()->size() icons, plus one extra if the page action had // a default icon. int total_icons = static_cast<int>(page_action_->icon_paths()->size()); @@ -188,11 +189,12 @@ void PageActionImageView::OnImageLoaded( // Map the index of the loaded image back to its name. If we ever get an // index greater than the number of icons, it must be the default icon. - if (image) { + if (!image.IsEmpty()) { + const SkBitmap* bitmap = image.ToSkBitmap(); if (index < static_cast<int>(page_action_->icon_paths()->size())) - page_action_icons_[page_action_->icon_paths()->at(index)] = *image; + page_action_icons_[page_action_->icon_paths()->at(index)] = *bitmap; else - page_action_icons_[page_action_->default_icon_path()] = *image; + page_action_icons_[page_action_->default_icon_path()] = *bitmap; } // During object construction (before the parent has been set) we are already diff --git a/chrome/browser/ui/views/location_bar/page_action_image_view.h b/chrome/browser/ui/views/location_bar/page_action_image_view.h index 98b824b..1390189 100644 --- a/chrome/browser/ui/views/location_bar/page_action_image_view.h +++ b/chrome/browser/ui/views/location_bar/page_action_image_view.h @@ -53,8 +53,8 @@ class PageActionImageView : public views::ImageView, bool is_mouse_gesture) OVERRIDE; // Overridden from ImageLoadingTracker. - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE; // Overridden from ExtensionContextMenuModelModel::Delegate diff --git a/chrome/browser/ui/web_applications/web_app_ui.cc b/chrome/browser/ui/web_applications/web_app_ui.cc index 1d3103a..c408987 100644 --- a/chrome/browser/ui/web_applications/web_app_ui.cc +++ b/chrome/browser/ui/web_applications/web_app_ui.cc @@ -162,7 +162,7 @@ void UpdateShortcutWorker::OnIconDownloaded(int download_id, if (!errored && !image.isNull()) { // Update icon with download image and update shortcut. - shortcut_info_.favicon = image; + shortcut_info_.favicon = gfx::Image(image); tab_contents_->extension_tab_helper()->SetAppIcon(image); UpdateShortcuts(); } else { @@ -309,7 +309,8 @@ void GetShortcutInfoForTab(TabContentsWrapper* tab_contents_wrapper, web_contents->GetTitle()) : app_info.title; info->description = app_info.description; - info->favicon = tab_contents_wrapper->favicon_tab_helper()->GetFavicon(); + info->favicon = + gfx::Image(tab_contents_wrapper->favicon_tab_helper()->GetFavicon()); } void UpdateShortcutForTabContents(TabContentsWrapper* tab_contents) { diff --git a/chrome/browser/ui/webui/extensions/extension_icon_source.cc b/chrome/browser/ui/webui/extensions/extension_icon_source.cc index 0aa3066..ca34c99 100644 --- a/chrome/browser/ui/webui/extensions/extension_icon_source.cc +++ b/chrome/browser/ui/webui/extensions/extension_icon_source.cc @@ -37,9 +37,9 @@ scoped_refptr<RefCountedMemory> BitmapToMemory(const SkBitmap* image) { return image_bytes; } -void DesaturateImage(SkBitmap* image) { +SkBitmap DesaturateImage(const SkBitmap* image) { color_utils::HSL shift = {-1, 0, 0.6}; - *image = SkBitmapOperations::CreateHSLShiftedBitmap(*image, shift); + return SkBitmapOperations::CreateHSLShiftedBitmap(*image, shift); } SkBitmap* ToBitmap(const unsigned char* data, size_t size) { @@ -168,13 +168,16 @@ const SkBitmap* ExtensionIconSource::GetDefaultExtensionImage() { return default_extension_data_.get(); } -void ExtensionIconSource::FinalizeImage(SkBitmap* image, +void ExtensionIconSource::FinalizeImage(const SkBitmap* image, int request_id) { + SkBitmap bitmap; if (GetData(request_id)->grayscale) - DesaturateImage(image); + bitmap = DesaturateImage(image); + else + bitmap = *image; ClearData(request_id); - SendResponse(request_id, BitmapToMemory(image)); + SendResponse(request_id, BitmapToMemory(&bitmap)); } void ExtensionIconSource::LoadDefaultImage(int request_id) { @@ -274,16 +277,16 @@ void ExtensionIconSource::OnFaviconDataAvailable( } } -void ExtensionIconSource::OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, +void ExtensionIconSource::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) { int request_id = tracker_map_[index]; tracker_map_.erase(tracker_map_.find(index)); - if (!image || image->empty()) + if (image.IsEmpty()) LoadIconFailed(request_id); else - FinalizeImage(image, request_id); + FinalizeImage(image.ToSkBitmap(), request_id); } bool ExtensionIconSource::ParseData(const std::string& path, diff --git a/chrome/browser/ui/webui/extensions/extension_icon_source.h b/chrome/browser/ui/webui/extensions/extension_icon_source.h index d790748c..4ea40fe 100644 --- a/chrome/browser/ui/webui/extensions/extension_icon_source.h +++ b/chrome/browser/ui/webui/extensions/extension_icon_source.h @@ -90,7 +90,7 @@ class ExtensionIconSource : public ChromeURLDataManager::DataSource, // Performs any remaining transformations (like desaturating the |image|), // then returns the |image| to the client and clears up any temporary data // associated with the |request_id|. - void FinalizeImage(SkBitmap* image, int request_id); + void FinalizeImage(const SkBitmap* image, int request_id); // Loads the default image for |request_id| and returns to the client. void LoadDefaultImage(int request_id); @@ -114,8 +114,8 @@ class ExtensionIconSource : public ChromeURLDataManager::DataSource, history::FaviconData favicon); // ImageLoadingTracker::Observer - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int id) OVERRIDE; // Called when the extension doesn't have an icon. We fall back to multiple diff --git a/chrome/browser/ui/webui/ntp/favicon_webui_handler.cc b/chrome/browser/ui/webui/ntp/favicon_webui_handler.cc index d4e9d5f..c10c14a 100644 --- a/chrome/browser/ui/webui/ntp/favicon_webui_handler.cc +++ b/chrome/browser/ui/webui/ntp/favicon_webui_handler.cc @@ -50,11 +50,11 @@ class ExtensionIconColorManager : public ExtensionIconManager { handler_(handler) {} virtual ~ExtensionIconColorManager() {} - virtual void OnImageLoaded(SkBitmap* image, - const ExtensionResource& resource, + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, int index) OVERRIDE { - ExtensionIconManager::OnImageLoaded(image, resource, index); - handler_->NotifyAppIconReady(resource.extension_id()); + ExtensionIconManager::OnImageLoaded(image, extension_id, index); + handler_->NotifyAppIconReady(extension_id); } private: diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm index 004f8d4..9cc1931 100644 --- a/chrome/browser/web_applications/web_app_mac.mm +++ b/chrome/browser/web_applications/web_app_mac.mm @@ -35,6 +35,48 @@ NSBitmapImageRep* SkBitmapToImageRep(const SkBitmap& bitmap) { [[image representations] lastObject]); } +// Adds |image_rep| to |icon_family|. Returns true on success, false on failure. +bool AddBitmapImageRepToIconFamily(IconFamily* icon_family, + NSBitmapImageRep* image_rep) { + NSSize size = [image_rep size]; + if (size.width != size.height) + return false; + + switch (static_cast<int>(size.width)) { + case 512: + return [icon_family setIconFamilyElement:kIconServices512PixelDataARGB + fromBitmapImageRep:image_rep]; + case 256: + return [icon_family setIconFamilyElement:kIconServices256PixelDataARGB + fromBitmapImageRep:image_rep]; + case 128: + return [icon_family setIconFamilyElement:kThumbnail32BitData + fromBitmapImageRep:image_rep] && + [icon_family setIconFamilyElement:kThumbnail8BitMask + fromBitmapImageRep:image_rep]; + case 32: + return [icon_family setIconFamilyElement:kLarge32BitData + fromBitmapImageRep:image_rep] && + [icon_family setIconFamilyElement:kLarge8BitData + fromBitmapImageRep:image_rep] && + [icon_family setIconFamilyElement:kLarge8BitMask + fromBitmapImageRep:image_rep] && + [icon_family setIconFamilyElement:kLarge1BitMask + fromBitmapImageRep:image_rep]; + case 16: + return [icon_family setIconFamilyElement:kSmall32BitData + fromBitmapImageRep:image_rep] && + [icon_family setIconFamilyElement:kSmall8BitData + fromBitmapImageRep:image_rep] && + [icon_family setIconFamilyElement:kSmall8BitMask + fromBitmapImageRep:image_rep] && + [icon_family setIconFamilyElement:kSmall1BitMask + fromBitmapImageRep:image_rep]; + default: + return false; + } +} + } // namespace @@ -150,26 +192,26 @@ bool WebAppShortcutCreator::UpdatePlist(const FilePath& app_path) const { } bool WebAppShortcutCreator::UpdateIcon(const FilePath& app_path) const { - // TODO(sail): Add support for multiple icon sizes. - if (info_.favicon.empty() || info_.favicon.width() != 32 || - info_.favicon.height() != 32) { + if (info_.favicon.IsEmpty()) return true; - } - - NSBitmapImageRep* image_rep = SkBitmapToImageRep(info_.favicon); - if (!image_rep) - return false; scoped_nsobject<IconFamily> icon_family([[IconFamily alloc] init]); - bool success = [icon_family setIconFamilyElement:kLarge32BitData - fromBitmapImageRep:image_rep] && - [icon_family setIconFamilyElement:kLarge8BitData - fromBitmapImageRep:image_rep] && - [icon_family setIconFamilyElement:kLarge8BitMask - fromBitmapImageRep:image_rep] && - [icon_family setIconFamilyElement:kLarge1BitMask - fromBitmapImageRep:image_rep]; - if (!success) + bool image_added = false; + for (size_t i = 0; i < info_.favicon.GetNumberOfSkBitmaps(); ++i) { + NSBitmapImageRep* image_rep = + SkBitmapToImageRep(*info_.favicon.GetSkBitmapAtIndex(i)); + if (!image_rep) + continue; + + // Missing an icon size is not fatal so don't fail if adding the bitmap + // doesn't work. + if (!AddBitmapImageRepToIconFamily(icon_family, image_rep)) + continue; + + image_added = true; + } + + if (!image_added) return false; FilePath resources_path = app_path.Append("Contents").Append("Resources"); diff --git a/chrome/browser/web_applications/web_app_mac_unittest.mm b/chrome/browser/web_applications/web_app_mac_unittest.mm index a2b78dc..f98757a 100644 --- a/chrome/browser/web_applications/web_app_mac_unittest.mm +++ b/chrome/browser/web_applications/web_app_mac_unittest.mm @@ -103,8 +103,8 @@ TEST(WebAppShortcutCreatorTest, UpdateIcon) { FilePath dst_path = scoped_temp_dir.path(); ShellIntegration::ShortcutInfo info = GetShortcutInfo(); - info.favicon = *ui::ResourceBundle::GetSharedInstance().GetImageNamed( - IDR_PRODUCT_LOGO_32).ToSkBitmap(); + info.favicon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( + IDR_PRODUCT_LOGO_32); WebAppShortcutCreatorMock shortcut_creator(info); shortcut_creator.UpdateIcon(dst_path); @@ -114,8 +114,8 @@ TEST(WebAppShortcutCreatorTest, UpdateIcon) { scoped_nsobject<NSImage> image([[NSImage alloc] initWithContentsOfFile: base::mac::FilePathToNSString(icon_path)]); EXPECT_TRUE(image); - EXPECT_EQ(info.favicon.width(), [image size].width); - EXPECT_EQ(info.favicon.height(), [image size].height); + EXPECT_EQ(info.favicon.ToSkBitmap()->width(), [image size].width); + EXPECT_EQ(info.favicon.ToSkBitmap()->height(), [image size].height); } } // namespace web_app |