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..7695b4ae0d74f0dff93cbcfaac97b0bb0015648b |
--- /dev/null |
+++ b/chrome/browser/extensions/extension_icon_image.cc |
@@ -0,0 +1,168 @@ |
+// 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/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 |
+ |
+namespace extensions { |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ExtensionIconImage::Source |
+ |
+class IconImage::Source : public gfx::ImageSkiaSource { |
+ public: |
+ explicit Source(IconImage* host); |
+ virtual ~Source(); |
+ |
+ void ResetHost(); |
+ |
+ private: |
+ // gfx::ImageSkiaSource overrides: |
+ virtual gfx::ImageSkiaRep GetImageForScale( |
+ ui::ScaleFactor scale_factor) OVERRIDE; |
+ |
+ IconImage* host_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Source); |
+}; |
+ |
+IconImage::Source::Source(IconImage* host) : host_(host) { |
+} |
+ |
+IconImage::Source::~Source() { |
+} |
+ |
+void IconImage::Source::ResetHost() { |
+ host_ = NULL; |
+} |
+ |
+gfx::ImageSkiaRep IconImage::Source::GetImageForScale( |
+ ui::ScaleFactor scale_factor) { |
+ if (host_) |
+ host_->LoadImageForScaleFactor(scale_factor); |
+ return gfx::ImageSkiaRep(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ExtensionIconImage |
+ |
+IconImage::IconImage( |
+ const 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, |
+ Delegate* 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)) { |
+ source_ = new Source(this); |
+ image_skia_ = gfx::ImageSkia(source_, desired_size_in_dip_); |
+ |
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
+ content::NotificationService::AllSources()); |
+} |
+ |
+IconImage::~IconImage() { |
+ // |source_| could be NULL if resource does not exist. |
+ if (source_) |
+ source_->ResetHost(); |
+} |
+ |
+void IconImage::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_); |
+ |
+ int id = tracker_.next_id(); |
+ load_map_[id] = scale_factor; |
+ |
+ std::vector<ImageLoadingTracker::ImageRepresentation> info_list; |
+ info_list.push_back(ImageLoadingTracker::ImageRepresentation( |
+ resource, |
+ ImageLoadingTracker::ImageRepresentation::ALWAYS_RESIZE, |
+ desired_size_in_dip_.Scale(scale), |
+ scale_factor)); |
+ tracker_.LoadImages(extension_, info_list, cache_param_); |
+} |
+ |
+void IconImage::OnImageLoaded(const gfx::Image& image, |
+ const std::string& extension_id, |
+ int index) { |
+ LoadMap::iterator load_map_it = load_map_.find(index); |
+ DCHECK(load_map_it != load_map_.end()); |
+ |
+ ui::ScaleFactor scale_factor = load_map_it->second; |
+ |
+ load_map_.erase(load_map_it); |
+ |
+ // If we were unable to load desired image, fallback to 1x scale factor. |
+ if (image.IsEmpty()) { |
+ if (scale_factor != ui::SCALE_FACTOR_100P && |
+ !image_skia_.HasRepresentation(ui::SCALE_FACTOR_100P)) { |
+ LoadImageForScaleFactor(ui::SCALE_FACTOR_100P); |
+ } |
+ return; |
+ } |
+ |
+ DCHECK(image.ToImageSkia()->HasRepresentation(scale_factor)); |
+ gfx::ImageSkiaRep rep = image.ToImageSkia()->GetRepresentation(scale_factor); |
+ DCHECK(!rep.is_null()); |
+ image_skia_.AddRepresentation(rep); |
+ |
+ if (delegate_) |
+ delegate_->OnExtensionIconImageChanged(this); |
+} |
+ |
+void IconImage::Observe(int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ DCHECK_EQ(type, chrome::NOTIFICATION_EXTENSION_UNLOADED); |
+ |
+ const Extension* extension = |
+ content::Details<extensions::UnloadedExtensionInfo>(details)->extension; |
+ |
+ if (extension_ == extension) |
+ extension_ = NULL; |
+} |
+ |
+} // namespace extensions |