blob: b035350fd7b61ce71ec3c32a9d78e7d2e28b9b1c [file] [log] [blame]
// 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_manager.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "extensions/browser/image_loader.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_icon_set.h"
#include "extensions/common/extension_resource.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "skia/ext/image_operations.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/native_theme/common_theme.h"
#include "ui/native_theme/native_theme.h"
ExtensionIconManager::ExtensionIconManager() {}
ExtensionIconManager::~ExtensionIconManager() {}
void ExtensionIconManager::LoadIcon(content::BrowserContext* context,
const extensions::Extension* extension) {
// Insert into pending_icons_ first because LoadImage can call us back
// synchronously if the image is already cached.
pending_icons_.insert(extension->id());
extensions::ImageLoader* loader = extensions::ImageLoader::Get(context);
loader->LoadImageAtEveryScaleFactorAsync(
extension, gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize),
base::Bind(&ExtensionIconManager::OnImageLoaded,
weak_ptr_factory_.GetWeakPtr(), extension->id()));
}
gfx::Image ExtensionIconManager::GetIcon(const std::string& extension_id) {
auto iter = icons_.find(extension_id);
gfx::Image* result = nullptr;
if (iter == icons_.end()) {
EnsureDefaultIcon();
result = &default_icon_;
} else {
result = &iter->second;
}
DCHECK(result);
DCHECK_EQ(gfx::kFaviconSize, result->Width());
DCHECK_EQ(gfx::kFaviconSize, result->Height());
return *result;
}
void ExtensionIconManager::RemoveIcon(const std::string& extension_id) {
icons_.erase(extension_id);
pending_icons_.erase(extension_id);
}
void ExtensionIconManager::OnImageLoaded(const std::string& extension_id,
const gfx::Image& image) {
if (!image.IsEmpty()) {
// We may have removed the icon while waiting for it to load. In that case,
// do nothing.
if (pending_icons_.erase(extension_id) == 0)
return;
gfx::Image modified_image = image;
if (monochrome_) {
color_utils::HSL shift = {-1, 0, 0.6};
modified_image =
gfx::Image(gfx::ImageSkiaOperations::CreateHSLShiftedImage(
image.AsImageSkia(), shift));
}
icons_[extension_id] = modified_image;
}
if (observer_)
observer_->OnImageLoaded(extension_id);
}
void ExtensionIconManager::EnsureDefaultIcon() {
if (default_icon_.IsEmpty()) {
default_icon_ = gfx::Image(gfx::CreateVectorIcon(
kExtensionIcon, gfx::kFaviconSize, gfx::kChromeIconGrey));
}
}