1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/app_icon_loader_impl.h" 6 7 #include "base/stl_util.h" 8 #include "chrome/browser/extensions/extension_service.h" 9 #include "chrome/browser/extensions/extension_util.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/common/extensions/extension_constants.h" 12 #include "extensions/browser/extension_system.h" 13 #include "extensions/common/extension.h" 14 #include "extensions/common/manifest_handlers/icons_handler.h" 15 #include "ui/gfx/color_utils.h" 16 #include "ui/gfx/image/image_skia_operations.h" 17 18 namespace { 19 20 const extensions::Extension* GetExtensionByID(Profile* profile, 21 const std::string& id) { 22 ExtensionService* service = 23 extensions::ExtensionSystem::Get(profile)->extension_service(); 24 if (!service) 25 return NULL; 26 return service->GetInstalledExtension(id); 27 } 28 29 } // namespace 30 31 namespace extensions { 32 33 AppIconLoaderImpl::AppIconLoaderImpl( 34 Profile* profile, 35 int icon_size, 36 AppIconLoader::Delegate* delegate) 37 : profile_(profile), 38 delegate_(delegate), 39 icon_size_(icon_size) { 40 41 } 42 43 AppIconLoaderImpl::~AppIconLoaderImpl() { 44 STLDeleteContainerPairFirstPointers(map_.begin(), map_.end()); 45 } 46 47 void AppIconLoaderImpl::FetchImage(const std::string& id) { 48 for (ImageToExtensionIDMap::const_iterator i = map_.begin(); 49 i != map_.end(); ++i) { 50 if (i->second == id) 51 return; // Already loading the image. 52 } 53 54 const extensions::Extension* extension = GetExtensionByID(profile_, id); 55 if (!extension) 56 return; 57 58 extensions::IconImage* image = new extensions::IconImage( 59 profile_, 60 extension, 61 extensions::IconsInfo::GetIcons(extension), 62 icon_size_, 63 extensions::util::GetDefaultAppIcon(), 64 this); 65 // |map_| takes ownership of |image|. 66 map_[image] = id; 67 68 // Triggers image loading now instead of depending on paint message. This 69 // makes the temp blank image be shown for shorter time and improves user 70 // experience. See http://crbug.com/146114. 71 image->image_skia().EnsureRepsForSupportedScales(); 72 } 73 74 void AppIconLoaderImpl::ClearImage(const std::string& id) { 75 for (ImageToExtensionIDMap::iterator i = map_.begin(); 76 i != map_.end(); ++i) { 77 if (i->second == id) { 78 delete i->first; 79 map_.erase(i); 80 break; 81 } 82 } 83 } 84 85 void AppIconLoaderImpl::UpdateImage(const std::string& id) { 86 for (ImageToExtensionIDMap::iterator i = map_.begin(); 87 i != map_.end(); ++i) { 88 if (i->second == id) { 89 BuildImage(i->second, i->first->image_skia()); 90 break; 91 } 92 } 93 } 94 95 void AppIconLoaderImpl::OnExtensionIconImageChanged( 96 extensions::IconImage* image) { 97 ImageToExtensionIDMap::iterator i = map_.find(image); 98 if (i == map_.end()) 99 return; // The image has been removed, do nothing. 100 101 BuildImage(i->second, i->first->image_skia()); 102 } 103 104 void AppIconLoaderImpl::BuildImage(const std::string& id, 105 const gfx::ImageSkia& icon) { 106 gfx::ImageSkia image = icon; 107 108 if (!util::IsAppLaunchable(id, profile_)) { 109 const color_utils::HSL shift = {-1, 0, 0.6}; 110 image = gfx::ImageSkiaOperations::CreateHSLShiftedImage(image, shift); 111 } 112 113 delegate_->SetAppImage(id, image); 114 } 115 116 } // namespace extensions 117