| 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..95f99d78ca3a9724e1a4c1a465856abe57d876e8
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/extension_icon_image.cc
|
| @@ -0,0 +1,177 @@
|
| +// 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);
|
| + return;
|
| + }
|
| +
|
| + 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;
|
| + 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 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;
|
| +}
|
|
|