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
IconManager()19 IconManager::IconManager() {
20 }
21
~IconManager()22 IconManager::~IconManager() {
23 STLDeleteValues(&icon_cache_);
24 }
25
LookupIcon(const FilePath & file_name,IconLoader::IconSize size)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
LoadIcon(const FilePath & file_name,IconLoader::IconSize size,CancelableRequestConsumerBase * consumer,IconRequestCallback * callback)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
OnImageLoaded(IconLoader * source,gfx::Image * result)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
CacheKey(const IconGroupID & group,IconLoader::IconSize size)93 IconManager::CacheKey::CacheKey(const IconGroupID& group,
94 IconLoader::IconSize size)
95 : group(group),
96 size(size) {
97 }
98
operator <(const CacheKey & other) const99 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