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..dcd096815c03ab6c26653705b041539a73703acc |
--- /dev/null |
+++ b/chrome/browser/extensions/extension_icon_image.cc |
@@ -0,0 +1,180 @@ |
+// 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 { |
+ |
+const int kMatchBiggerTreshold = 32; |
+ |
+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, |
+ Observer* observer) |
+ : extension_(extension), |
+ icon_set_(icon_set), |
+ resource_size_in_dip_(resource_size_in_dip), |
+ desired_size_in_dip_(resource_size_in_dip, resource_size_in_dip), |
+ observer_(observer), |
+ 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; |
+ // We try loading bigger image only if resource size is >= 32. |
+ if (resource_size_in_pixel >= kMatchBiggerTreshold) { |
+ resource = GetExtensionIconResource(extension_, icon_set_, |
+ resource_size_in_pixel, ExtensionIconSet::MATCH_BIGGER); |
+ } |
+ |
+ // If resource is not found by now, try matching smaller one. |
+ if (resource.empty()) { |
+ resource = GetExtensionIconResource(extension_, icon_set_, |
+ resource_size_in_pixel, ExtensionIconSet::MATCH_SMALLER); |
+ } |
+ |
+ // If there is no resource found, bail out and notify observer of failure. |
+ if (resource.empty()) { |
+ if (observer_) |
+ observer_->OnIconImageLoadFailed(this, scale_factor); |
+ return; |
+ } |
+ |
+ 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::RESIZE_WHEN_LARGER, |
+ desired_size_in_dip_.Scale(scale), |
+ scale_factor)); |
+ tracker_.LoadImages(extension_, info_list, ImageLoadingTracker::DONT_CACHE); |
+} |
+ |
+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 (image.IsEmpty()) { |
+ // There waas an error loading the image. |
+ if (observer_) |
+ observer_->OnIconImageLoadFailed(this, scale_factor); |
+ return; |
+ } |
+ |
+ DCHECK(image.ToImageSkia()->HasRepresentation(scale_factor)); |
+ gfx::ImageSkiaRep rep = image.ToImageSkia()->GetRepresentation(scale_factor); |
+ DCHECK(!rep.is_null()); |
+ image_skia_.AddRepresentation(rep); |
+ |
+ if (observer_) |
+ observer_->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 |