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.
5 #include "chrome/browser/icon_manager.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/stl_util.h"
10 #include "base/task_runner.h"
11 #include "third_party/skia/include/core/SkBitmap.h"
12 #include "third_party/skia/include/core/SkCanvas.h"
16 void RunCallbackIfNotCanceled(
17 const base::CancelableTaskTracker::IsCanceledCallback
& is_canceled
,
18 const IconManager::IconRequestCallback
& callback
,
20 if (is_canceled
.Run())
27 struct IconManager::ClientRequest
{
28 IconRequestCallback callback
;
29 base::FilePath file_path
;
30 IconLoader::IconSize size
;
33 IconManager::IconManager() {
36 IconManager::~IconManager() {
37 STLDeleteValues(&icon_cache_
);
40 gfx::Image
* IconManager::LookupIconFromFilepath(const base::FilePath
& file_name
,
41 IconLoader::IconSize size
) {
42 GroupMap::iterator it
= group_cache_
.find(file_name
);
43 if (it
!= group_cache_
.end())
44 return LookupIconFromGroup(it
->second
, size
);
49 gfx::Image
* IconManager::LookupIconFromGroup(const IconGroupID
& group
,
50 IconLoader::IconSize size
) {
51 IconMap::iterator it
= icon_cache_
.find(CacheKey(group
, size
));
52 if (it
!= icon_cache_
.end())
58 base::CancelableTaskTracker::TaskId
IconManager::LoadIcon(
59 const base::FilePath
& file_name
,
60 IconLoader::IconSize size
,
61 const IconRequestCallback
& callback
,
62 base::CancelableTaskTracker
* tracker
) {
63 IconLoader
* loader
= new IconLoader(file_name
, size
, this);
67 base::CancelableTaskTracker::IsCanceledCallback is_canceled
;
68 base::CancelableTaskTracker::TaskId id
=
69 tracker
->NewTrackedTaskId(&is_canceled
);
70 IconRequestCallback callback_runner
= base::Bind(
71 &RunCallbackIfNotCanceled
, is_canceled
, callback
);
73 ClientRequest client_request
= { callback_runner
, file_name
, size
};
74 requests_
[loader
] = client_request
;
78 // IconLoader::Delegate implementation -----------------------------------------
80 bool IconManager::OnGroupLoaded(IconLoader
* loader
,
81 const IconGroupID
& group
) {
82 ClientRequests::iterator rit
= requests_
.find(loader
);
83 if (rit
== requests_
.end()) {
88 gfx::Image
* result
= LookupIconFromGroup(group
, rit
->second
.size
);
93 return OnImageLoaded(loader
, result
, group
);
96 bool IconManager::OnImageLoaded(
97 IconLoader
* loader
, gfx::Image
* result
, const IconGroupID
& group
) {
98 ClientRequests::iterator rit
= requests_
.find(loader
);
100 // Balances the AddRef() in LoadIcon().
103 // Look up our client state.
104 if (rit
== requests_
.end()) {
106 return false; // Return false to indicate result should be deleted.
109 const ClientRequest
& client_request
= rit
->second
;
111 // Cache the bitmap. Watch out: |result| may be NULL to indicate a current
112 // failure. We assume that if we have an entry in |icon_cache_|
113 // it must not be NULL.
114 CacheKey
key(group
, client_request
.size
);
115 IconMap::iterator it
= icon_cache_
.find(key
);
116 if (it
!= icon_cache_
.end()) {
119 icon_cache_
.erase(it
);
120 } else if (result
!= it
->second
) {
121 it
->second
->SwapRepresentations(result
);
126 icon_cache_
[key
] = result
;
129 group_cache_
[client_request
.file_path
] = group
;
131 // Inform our client that the request has completed.
132 client_request
.callback
.Run(result
);
133 requests_
.erase(rit
);
135 return true; // Indicates we took ownership of result.
138 IconManager::CacheKey::CacheKey(const IconGroupID
& group
,
139 IconLoader::IconSize size
)
144 bool IconManager::CacheKey::operator<(const CacheKey
&other
) const {
145 if (group
!= other
.group
)
146 return group
< other
.group
;
147 return size
< other
.size
;