Chromium Code Reviews| Index: chrome/browser/extensions/extension_icon_image.cc |
| diff --git a/chrome/browser/extensions/extension_icon_image.cc b/chrome/browser/extensions/extension_icon_image.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c09e76787716c10ae689c1189a88dba58e06740d |
| --- /dev/null |
| +++ b/chrome/browser/extensions/extension_icon_image.cc |
| @@ -0,0 +1,175 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/extensions/extension_icon_image.h" |
| + |
| +#include <vector> |
| + |
| +#include "chrome/browser/extensions/extension_icon_image_delegate.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| +#include "chrome/common/extensions/extension.h" |
| +#include "content/public/browser/notification_service.h" |
| +#include "ui/gfx/image/image.h" |
| +#include "ui/gfx/image/image_skia_source.h" |
| +#include "ui/gfx/size.h" |
| + |
| +namespace { |
| + |
| +ExtensionResource GetExtensionIconResource( |
| + const extensions::Extension* extension, |
| + const ExtensionIconSet& icons, |
| + int size, |
| + ExtensionIconSet::MatchType match_type) { |
| + std::string path = icons.Get(size, match_type); |
| + if (path.empty()) |
| + return ExtensionResource(); |
| + |
| + return extension->GetResource(path); |
| +} |
| + |
| +} // namespace |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// ExtensionIconImage::Source |
| + |
| +class ExtensionIconImage::Source : public gfx::ImageSkiaSource { |
| + public: |
| + explicit Source(ExtensionIconImage* host); |
| + virtual ~Source(); |
| + |
| + void ResetHost(); |
| + |
| + private: |
| + // gfx::ImageSkiaSource overrides: |
| + virtual gfx::ImageSkiaRep GetImageForScale( |
| + ui::ScaleFactor scale_factor) OVERRIDE; |
| + |
| + ExtensionIconImage* host_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Source); |
| +}; |
| + |
| +ExtensionIconImage::Source::Source(ExtensionIconImage* host) |
| + : host_(host) { |
| +} |
| + |
| +ExtensionIconImage::Source::~Source() { |
| +} |
| + |
| +void ExtensionIconImage::Source::ResetHost() { |
| + host_ = NULL; |
| +} |
| + |
| +gfx::ImageSkiaRep ExtensionIconImage::Source::GetImageForScale( |
| + ui::ScaleFactor scale_factor) { |
| + if (host_) |
| + host_->LoadImageForScaleFactor(scale_factor); |
| + return gfx::ImageSkiaRep(); |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// ExtensionIconImage |
| + |
| +ExtensionIconImage::ExtensionIconImage( |
| + const extensions::Extension* extension, |
| + const ExtensionIconSet& icon_set, |
| + int resource_size_in_dip, |
| + ExtensionIconSet::MatchType resource_match_type, |
| + const gfx::Size& desired_size_in_dip, |
| + ImageLoadingTracker::CacheParam cache_param, |
| + ExtensionIconImageDelegate* delegate) |
| + : extension_(extension), |
| + icon_set_(icon_set), |
| + resource_size_in_dip_(resource_size_in_dip), |
| + resource_match_type_(resource_match_type), |
| + desired_size_in_dip_(desired_size_in_dip), |
| + cache_param_(cache_param), |
| + delegate_(delegate), |
| + source_(NULL), |
| + ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { |
| + // Check whether extension has at least 1x resource. |
| + const int resource_size_in_pixel = resource_size_in_dip_; |
| + const bool can_load = ImageLoadingTracker::CanLoadImage( |
| + extension_, |
| + GetExtensionIconResource(extension_, |
| + icon_set_, |
| + resource_size_in_pixel, |
| + resource_match_type_)); |
| + if (!can_load) |
| + return; |
| + |
| + source_ = new Source(this); |
| + image_skia_ = gfx::ImageSkia(source_, desired_size_in_dip_); |
| + |
| + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| + content::NotificationService::AllSources()); |
| +} |
| + |
| +ExtensionIconImage::~ExtensionIconImage() { |
| + // |source_| could be NULL if resource does not exist. |
| + if (source_) |
| + source_->ResetHost(); |
| +} |
| + |
| +void ExtensionIconImage::LoadImageForScaleFactor(ui::ScaleFactor scale_factor) { |
| + // Do nothing if extension is unloaded. |
| + if (!extension_) |
| + return; |
| + |
| + const float scale = ui::GetScaleFactorScale(scale_factor); |
| + const int resource_size_in_pixel = |
| + static_cast<int>(resource_size_in_dip_ * scale); |
| + |
| + ExtensionResource resource = GetExtensionIconResource( |
| + extension_, icon_set_, resource_size_in_pixel, resource_match_type_); |
| + // If resource does not exists, fallback to 1x if needed. |
| + if (!ImageLoadingTracker::CanLoadImage(extension_, resource)) { |
| + scale_factor = ui::SCALE_FACTOR_100P; |
| + if (image_skia_.HasRepresentation(scale_factor)) |
| + return; |
| + |
| + LoadImageForScaleFactor(scale_factor); |
| + } |
| + |
| + int id = tracker_.next_id(); |
| + load_map_[id] = scale_factor; |
| + |
| + std::vector<ImageLoadingTracker::ImageRepInfo> info_list; |
| + info_list.push_back(ImageLoadingTracker::ImageRepInfo( |
| + resource, |
| + ImageLoadingTracker::ImageRepInfo::ALWAYS_RESIZE, |
| + desired_size_in_dip_.Scale(scale), |
| + scale_factor)); |
| + tracker_.LoadImages(extension_, info_list, cache_param_); |
| +} |
| + |
| +void ExtensionIconImage::OnImageLoaded(const gfx::Image& image, |
| + const std::string& extension_id, |
| + int index) { |
| + if (image.IsEmpty()) |
| + return; |
| + |
| + LoadMap::iterator load_map_it = load_map_.find(index); |
| + DCHECK(load_map_it != load_map_.end()); |
| + |
| + ui::ScaleFactor scale_factor = load_map_it->second; |
| + gfx::ImageSkiaRep rep = image.ToImageSkia()->GetRepresentation(scale_factor); |
|
tbarzic
2012/07/25 19:37:34
pkotwicz 2012/07/25 02:00:39
Nit: You can DCHECK o
tbarzic
2012/07/25 19:53:53
Done.
|
| + DCHECK(!rep.is_null()); |
| + image_skia_.AddRepresentation(rep); |
| + |
| + if (delegate_) |
| + delegate_->OnExtensionIconImageChanged(this); |
| +} |
| + |
| +void ExtensionIconImage::Observe(int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + DCHECK_EQ(type, chrome::NOTIFICATION_EXTENSION_UNLOADED); |
| + |
| + const extensions::Extension* extension = |
| + content::Details<extensions::UnloadedExtensionInfo>(details)->extension; |
| + |
| + if (extension_ == extension) |
| + extension_ = NULL; |
| +} |