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 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 CancelableTaskTracker::TaskId
IconManager::LoadIcon(
59 const base::FilePath
& file_name
,
60 IconLoader::IconSize size
,
61 const IconRequestCallback
& callback
,
62 CancelableTaskTracker
* tracker
) {
63 IconLoader
* loader
= new IconLoader(file_name
, size
, this);
67 CancelableTaskTracker::IsCanceledCallback is_canceled
;
68 CancelableTaskTracker::TaskId id
= tracker
->NewTrackedTaskId(&is_canceled
);
69 IconRequestCallback callback_runner
= base::Bind(
70 &RunCallbackIfNotCanceled
, is_canceled
, callback
);
72 ClientRequest client_request
= { callback_runner
, file_name
, size
};
73 requests_
[loader
] = client_request
;
77 // IconLoader::Delegate implementation -----------------------------------------
79 bool IconManager::OnGroupLoaded(IconLoader
* loader
,
80 const IconGroupID
& group
) {
81 ClientRequests::iterator rit
= requests_
.find(loader
);
82 if (rit
== requests_
.end()) {
87 gfx::Image
* result
= LookupIconFromGroup(group
, rit
->second
.size
);
92 return OnImageLoaded(loader
, result
, group
);
95 bool IconManager::OnImageLoaded(
96 IconLoader
* loader
, gfx::Image
* result
, const IconGroupID
& group
) {
97 ClientRequests::iterator rit
= requests_
.find(loader
);
99 // Balances the AddRef() in LoadIcon().
102 // Look up our client state.
103 if (rit
== requests_
.end()) {
105 return false; // Return false to indicate result should be deleted.
108 const ClientRequest
& client_request
= rit
->second
;
110 // Cache the bitmap. Watch out: |result| may be NULL to indicate a current
111 // failure. We assume that if we have an entry in |icon_cache_|
112 // it must not be NULL.
113 CacheKey
key(group
, client_request
.size
);
114 IconMap::iterator it
= icon_cache_
.find(key
);
115 if (it
!= icon_cache_
.end()) {
118 icon_cache_
.erase(it
);
119 } else if (result
!= it
->second
) {
120 it
->second
->SwapRepresentations(result
);
125 icon_cache_
[key
] = result
;
128 group_cache_
[client_request
.file_path
] = group
;
130 // Inform our client that the request has completed.
131 client_request
.callback
.Run(result
);
132 requests_
.erase(rit
);
134 return true; // Indicates we took ownership of result.
137 IconManager::CacheKey::CacheKey(const IconGroupID
& group
,
138 IconLoader::IconSize size
)
143 bool IconManager::CacheKey::operator<(const CacheKey
&other
) const {
144 if (group
!= other
.group
)
145 return group
< other
.group
;
146 return size
< other
.size
;