blob: 0b43141971b3ceeff2d5ed30472a4446b2bbbd11 [file] [log] [blame]
[email protected]66171ab2011-03-03 15:50:071// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/browser/icon_manager.h"
6
jsbell50f0e752015-11-16 19:36:537#include <tuple>
8
[email protected]c1896982012-12-05 20:26:179#include "base/bind.h"
[email protected]3b63f8f42011-03-28 01:54:1510#include "base/memory/scoped_ptr.h"
[email protected]7286e3fc2011-07-19 22:13:2411#include "base/stl_util.h"
[email protected]c1896982012-12-05 20:26:1712#include "base/task_runner.h"
[email protected]c43c6682009-05-19 14:51:4413#include "third_party/skia/include/core/SkBitmap.h"
14#include "third_party/skia/include/core/SkCanvas.h"
initial.commit09911bf2008-07-26 23:55:2915
[email protected]c1896982012-12-05 20:26:1716namespace {
17
18void RunCallbackIfNotCanceled(
[email protected]e95b717f2014-02-06 13:47:1319 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
[email protected]c1896982012-12-05 20:26:1720 const IconManager::IconRequestCallback& callback,
21 gfx::Image* image) {
22 if (is_canceled.Run())
23 return;
24 callback.Run(image);
25}
26
27} // namespace
28
[email protected]38e08982010-10-22 17:28:4329struct IconManager::ClientRequest {
[email protected]c1896982012-12-05 20:26:1730 IconRequestCallback callback;
[email protected]bc0147b2013-04-03 20:50:5931 base::FilePath file_path;
[email protected]38e08982010-10-22 17:28:4332 IconLoader::IconSize size;
33};
34
initial.commit09911bf2008-07-26 23:55:2935IconManager::IconManager() {
36}
37
38IconManager::~IconManager() {
39 STLDeleteValues(&icon_cache_);
40}
41
[email protected]bc0147b2013-04-03 20:50:5942gfx::Image* IconManager::LookupIconFromFilepath(const base::FilePath& file_name,
43 IconLoader::IconSize size) {
44 GroupMap::iterator it = group_cache_.find(file_name);
45 if (it != group_cache_.end())
46 return LookupIconFromGroup(it->second, size);
47
48 return NULL;
49}
50
51gfx::Image* IconManager::LookupIconFromGroup(const IconGroupID& group,
52 IconLoader::IconSize size) {
[email protected]0f38ceae2009-05-08 19:01:0253 IconMap::iterator it = icon_cache_.find(CacheKey(group, size));
initial.commit09911bf2008-07-26 23:55:2954 if (it != icon_cache_.end())
55 return it->second;
56
57 return NULL;
58}
59
[email protected]e95b717f2014-02-06 13:47:1360base::CancelableTaskTracker::TaskId IconManager::LoadIcon(
[email protected]650b2d52013-02-10 03:41:4561 const base::FilePath& file_name,
initial.commit09911bf2008-07-26 23:55:2962 IconLoader::IconSize size,
[email protected]c1896982012-12-05 20:26:1763 const IconRequestCallback& callback,
[email protected]e95b717f2014-02-06 13:47:1364 base::CancelableTaskTracker* tracker) {
[email protected]bc0147b2013-04-03 20:50:5965 IconLoader* loader = new IconLoader(file_name, size, this);
[email protected]46728b1f2009-05-07 20:42:2466 loader->AddRef();
initial.commit09911bf2008-07-26 23:55:2967 loader->Start();
[email protected]c1896982012-12-05 20:26:1768
[email protected]e95b717f2014-02-06 13:47:1369 base::CancelableTaskTracker::IsCanceledCallback is_canceled;
70 base::CancelableTaskTracker::TaskId id =
71 tracker->NewTrackedTaskId(&is_canceled);
[email protected]c1896982012-12-05 20:26:1772 IconRequestCallback callback_runner = base::Bind(
73 &RunCallbackIfNotCanceled, is_canceled, callback);
74
[email protected]bc0147b2013-04-03 20:50:5975 ClientRequest client_request = { callback_runner, file_name, size };
initial.commit09911bf2008-07-26 23:55:2976 requests_[loader] = client_request;
[email protected]c1896982012-12-05 20:26:1777 return id;
initial.commit09911bf2008-07-26 23:55:2978}
79
80// IconLoader::Delegate implementation -----------------------------------------
81
[email protected]bc0147b2013-04-03 20:50:5982bool IconManager::OnGroupLoaded(IconLoader* loader,
83 const IconGroupID& group) {
84 ClientRequests::iterator rit = requests_.find(loader);
85 if (rit == requests_.end()) {
86 NOTREACHED();
87 return false;
88 }
89
90 gfx::Image* result = LookupIconFromGroup(group, rit->second.size);
91 if (!result) {
92 return false;
93 }
94
95 return OnImageLoaded(loader, result, group);
96}
97
98bool IconManager::OnImageLoaded(
99 IconLoader* loader, gfx::Image* result, const IconGroupID& group) {
[email protected]c1896982012-12-05 20:26:17100 ClientRequests::iterator rit = requests_.find(loader);
101
[email protected]46728b1f2009-05-07 20:42:24102 // Balances the AddRef() in LoadIcon().
[email protected]c1896982012-12-05 20:26:17103 loader->Release();
initial.commit09911bf2008-07-26 23:55:29104
105 // Look up our client state.
initial.commit09911bf2008-07-26 23:55:29106 if (rit == requests_.end()) {
107 NOTREACHED();
[email protected]cf2ef752008-09-11 21:19:29108 return false; // Return false to indicate result should be deleted.
initial.commit09911bf2008-07-26 23:55:29109 }
110
[email protected]c1896982012-12-05 20:26:17111 const ClientRequest& client_request = rit->second;
initial.commit09911bf2008-07-26 23:55:29112
[email protected]0204a782013-10-24 03:18:59113 // Cache the bitmap. Watch out: |result| may be NULL to indicate a current
114 // failure. We assume that if we have an entry in |icon_cache_|
115 // it must not be NULL.
[email protected]bc0147b2013-04-03 20:50:59116 CacheKey key(group, client_request.size);
initial.commit09911bf2008-07-26 23:55:29117 IconMap::iterator it = icon_cache_.find(key);
[email protected]0204a782013-10-24 03:18:59118 if (it != icon_cache_.end()) {
119 if (!result) {
120 delete it->second;
121 icon_cache_.erase(it);
122 } else if (result != it->second) {
[email protected]bc0147b2013-04-03 20:50:59123 it->second->SwapRepresentations(result);
124 delete result;
125 result = it->second;
126 }
[email protected]0204a782013-10-24 03:18:59127 } else if (result) {
initial.commit09911bf2008-07-26 23:55:29128 icon_cache_[key] = result;
129 }
130
[email protected]bc0147b2013-04-03 20:50:59131 group_cache_[client_request.file_path] = group;
132
initial.commit09911bf2008-07-26 23:55:29133 // Inform our client that the request has completed.
[email protected]c1896982012-12-05 20:26:17134 client_request.callback.Run(result);
initial.commit09911bf2008-07-26 23:55:29135 requests_.erase(rit);
136
[email protected]cf2ef752008-09-11 21:19:29137 return true; // Indicates we took ownership of result.
initial.commit09911bf2008-07-26 23:55:29138}
139
[email protected]0f38ceae2009-05-08 19:01:02140IconManager::CacheKey::CacheKey(const IconGroupID& group,
initial.commit09911bf2008-07-26 23:55:29141 IconLoader::IconSize size)
[email protected]0f38ceae2009-05-08 19:01:02142 : group(group),
initial.commit09911bf2008-07-26 23:55:29143 size(size) {
144}
145
146bool IconManager::CacheKey::operator<(const CacheKey &other) const {
jsbell50f0e752015-11-16 19:36:53147 return std::tie(group, size) < std::tie(other.group, other.size);
initial.commit09911bf2008-07-26 23:55:29148}