1 // Copyright (c) 2011 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/icon_manager.h" 6 7 #include "base/file_util.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/stl_util-inl.h" 10 #include "third_party/skia/include/core/SkBitmap.h" 11 #include "third_party/skia/include/core/SkCanvas.h" 12 13 struct IconManager::ClientRequest { 14 scoped_refptr<IconRequest> request; 15 IconGroupID group; 16 IconLoader::IconSize size; 17 }; 18 19 IconManager::IconManager() { 20 } 21 22 IconManager::~IconManager() { 23 STLDeleteValues(&icon_cache_); 24 } 25 26 gfx::Image* IconManager::LookupIcon(const FilePath& file_name, 27 IconLoader::IconSize size) { 28 IconGroupID group = GetGroupIDFromFilepath(file_name); 29 IconMap::iterator it = icon_cache_.find(CacheKey(group, size)); 30 if (it != icon_cache_.end()) 31 return it->second; 32 33 return NULL; 34 } 35 36 IconManager::Handle IconManager::LoadIcon( 37 const FilePath& file_name, 38 IconLoader::IconSize size, 39 CancelableRequestConsumerBase* consumer, 40 IconRequestCallback* callback) { 41 IconGroupID group = GetGroupIDFromFilepath(file_name); 42 IconRequest* request = new IconRequest(callback); 43 AddRequest(request, consumer); 44 45 IconLoader* loader = new IconLoader(group, size, this); 46 loader->AddRef(); 47 loader->Start(); 48 ClientRequest client_request = { request, group, size }; 49 requests_[loader] = client_request; 50 return request->handle(); 51 } 52 53 // IconLoader::Delegate implementation ----------------------------------------- 54 55 bool IconManager::OnImageLoaded(IconLoader* source, gfx::Image* result) { 56 ClientRequests::iterator rit = requests_.find(source); 57 // Balances the AddRef() in LoadIcon(). 58 source->Release(); 59 60 // Look up our client state. 61 if (rit == requests_.end()) { 62 NOTREACHED(); 63 return false; // Return false to indicate result should be deleted. 64 } 65 66 ClientRequest client_request = rit->second; 67 if (client_request.request->canceled()) { 68 requests_.erase(rit); 69 return false; // Return false to indicate result should be deleted. 70 } 71 72 // Cache the bitmap. Watch out: |result| or the cached bitmap may be NULL to 73 // indicate a current or past failure. 74 CacheKey key(client_request.group, client_request.size); 75 IconMap::iterator it = icon_cache_.find(key); 76 if (it != icon_cache_.end() && result && it->second) { 77 it->second->SwapRepresentations(result); 78 delete result; 79 result = it->second; 80 } else { 81 icon_cache_[key] = result; 82 } 83 84 // Inform our client that the request has completed. 85 IconRequest* icon_request = client_request.request; 86 icon_request->ForwardResult(IconRequest::TupleType(icon_request->handle(), 87 result)); 88 requests_.erase(rit); 89 90 return true; // Indicates we took ownership of result. 91 } 92 93 IconManager::CacheKey::CacheKey(const IconGroupID& group, 94 IconLoader::IconSize size) 95 : group(group), 96 size(size) { 97 } 98 99 bool IconManager::CacheKey::operator<(const CacheKey &other) const { 100 if (group != other.group) 101 return group < other.group; 102 return size < other.size; 103 } 104