Popular sites on the NTP: re-download popular suggestions once per Chrome run
[chromium-blink-merge.git] / chrome / browser / icon_manager.cc
bloba329249f0ebba8fe652ea2c9b5ec824ac54923ab
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"
7 #include "base/bind.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"
14 namespace {
16 void RunCallbackIfNotCanceled(
17 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
18 const IconManager::IconRequestCallback& callback,
19 gfx::Image* image) {
20 if (is_canceled.Run())
21 return;
22 callback.Run(image);
25 } // namespace
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);
46 return NULL;
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())
53 return it->second;
55 return NULL;
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);
64 loader->AddRef();
65 loader->Start();
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;
75 return id;
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()) {
84 NOTREACHED();
85 return false;
88 gfx::Image* result = LookupIconFromGroup(group, rit->second.size);
89 if (!result) {
90 return false;
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().
101 loader->Release();
103 // Look up our client state.
104 if (rit == requests_.end()) {
105 NOTREACHED();
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()) {
117 if (!result) {
118 delete it->second;
119 icon_cache_.erase(it);
120 } else if (result != it->second) {
121 it->second->SwapRepresentations(result);
122 delete result;
123 result = it->second;
125 } else if (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)
140 : group(group),
141 size(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;