blob: a329249f0ebba8fe652ea2c9b5ec824ac54923ab [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
[email protected]c1896982012-12-05 20:26:177#include "base/bind.h"
[email protected]3b63f8f42011-03-28 01:54:158#include "base/memory/scoped_ptr.h"
[email protected]7286e3fc2011-07-19 22:13:249#include "base/stl_util.h"
[email protected]c1896982012-12-05 20:26:1710#include "base/task_runner.h"
[email protected]c43c6682009-05-19 14:51:4411#include "third_party/skia/include/core/SkBitmap.h"
12#include "third_party/skia/include/core/SkCanvas.h"
initial.commit09911bf2008-07-26 23:55:2913
[email protected]c1896982012-12-05 20:26:1714namespace {
15
16void RunCallbackIfNotCanceled(
[email protected]e95b717f2014-02-06 13:47:1317 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
[email protected]c1896982012-12-05 20:26:1718 const IconManager::IconRequestCallback& callback,
19 gfx::Image* image) {
20 if (is_canceled.Run())
21 return;
22 callback.Run(image);
23}
24
25} // namespace
26
[email protected]38e08982010-10-22 17:28:4327struct IconManager::ClientRequest {
[email protected]c1896982012-12-05 20:26:1728 IconRequestCallback callback;
[email protected]bc0147b2013-04-03 20:50:5929 base::FilePath file_path;
[email protected]38e08982010-10-22 17:28:4330 IconLoader::IconSize size;
31};
32
initial.commit09911bf2008-07-26 23:55:2933IconManager::IconManager() {
34}
35
36IconManager::~IconManager() {
37 STLDeleteValues(&icon_cache_);
38}
39
[email protected]bc0147b2013-04-03 20:50:5940gfx::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);
45
46 return NULL;
47}
48
49gfx::Image* IconManager::LookupIconFromGroup(const IconGroupID& group,
50 IconLoader::IconSize size) {
[email protected]0f38ceae2009-05-08 19:01:0251 IconMap::iterator it = icon_cache_.find(CacheKey(group, size));
initial.commit09911bf2008-07-26 23:55:2952 if (it != icon_cache_.end())
53 return it->second;
54
55 return NULL;
56}
57
[email protected]e95b717f2014-02-06 13:47:1358base::CancelableTaskTracker::TaskId IconManager::LoadIcon(
[email protected]650b2d52013-02-10 03:41:4559 const base::FilePath& file_name,
initial.commit09911bf2008-07-26 23:55:2960 IconLoader::IconSize size,
[email protected]c1896982012-12-05 20:26:1761 const IconRequestCallback& callback,
[email protected]e95b717f2014-02-06 13:47:1362 base::CancelableTaskTracker* tracker) {
[email protected]bc0147b2013-04-03 20:50:5963 IconLoader* loader = new IconLoader(file_name, size, this);
[email protected]46728b1f2009-05-07 20:42:2464 loader->AddRef();
initial.commit09911bf2008-07-26 23:55:2965 loader->Start();
[email protected]c1896982012-12-05 20:26:1766
[email protected]e95b717f2014-02-06 13:47:1367 base::CancelableTaskTracker::IsCanceledCallback is_canceled;
68 base::CancelableTaskTracker::TaskId id =
69 tracker->NewTrackedTaskId(&is_canceled);
[email protected]c1896982012-12-05 20:26:1770 IconRequestCallback callback_runner = base::Bind(
71 &RunCallbackIfNotCanceled, is_canceled, callback);
72
[email protected]bc0147b2013-04-03 20:50:5973 ClientRequest client_request = { callback_runner, file_name, size };
initial.commit09911bf2008-07-26 23:55:2974 requests_[loader] = client_request;
[email protected]c1896982012-12-05 20:26:1775 return id;
initial.commit09911bf2008-07-26 23:55:2976}
77
78// IconLoader::Delegate implementation -----------------------------------------
79
[email protected]bc0147b2013-04-03 20:50:5980bool 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;
86 }
87
88 gfx::Image* result = LookupIconFromGroup(group, rit->second.size);
89 if (!result) {
90 return false;
91 }
92
93 return OnImageLoaded(loader, result, group);
94}
95
96bool IconManager::OnImageLoaded(
97 IconLoader* loader, gfx::Image* result, const IconGroupID& group) {
[email protected]c1896982012-12-05 20:26:1798 ClientRequests::iterator rit = requests_.find(loader);
99
[email protected]46728b1f2009-05-07 20:42:24100 // Balances the AddRef() in LoadIcon().
[email protected]c1896982012-12-05 20:26:17101 loader->Release();
initial.commit09911bf2008-07-26 23:55:29102
103 // Look up our client state.
initial.commit09911bf2008-07-26 23:55:29104 if (rit == requests_.end()) {
105 NOTREACHED();
[email protected]cf2ef752008-09-11 21:19:29106 return false; // Return false to indicate result should be deleted.
initial.commit09911bf2008-07-26 23:55:29107 }
108
[email protected]c1896982012-12-05 20:26:17109 const ClientRequest& client_request = rit->second;
initial.commit09911bf2008-07-26 23:55:29110
[email protected]0204a782013-10-24 03:18:59111 // 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.
[email protected]bc0147b2013-04-03 20:50:59114 CacheKey key(group, client_request.size);
initial.commit09911bf2008-07-26 23:55:29115 IconMap::iterator it = icon_cache_.find(key);
[email protected]0204a782013-10-24 03:18:59116 if (it != icon_cache_.end()) {
117 if (!result) {
118 delete it->second;
119 icon_cache_.erase(it);
120 } else if (result != it->second) {
[email protected]bc0147b2013-04-03 20:50:59121 it->second->SwapRepresentations(result);
122 delete result;
123 result = it->second;
124 }
[email protected]0204a782013-10-24 03:18:59125 } else if (result) {
initial.commit09911bf2008-07-26 23:55:29126 icon_cache_[key] = result;
127 }
128
[email protected]bc0147b2013-04-03 20:50:59129 group_cache_[client_request.file_path] = group;
130
initial.commit09911bf2008-07-26 23:55:29131 // Inform our client that the request has completed.
[email protected]c1896982012-12-05 20:26:17132 client_request.callback.Run(result);
initial.commit09911bf2008-07-26 23:55:29133 requests_.erase(rit);
134
[email protected]cf2ef752008-09-11 21:19:29135 return true; // Indicates we took ownership of result.
initial.commit09911bf2008-07-26 23:55:29136}
137
[email protected]0f38ceae2009-05-08 19:01:02138IconManager::CacheKey::CacheKey(const IconGroupID& group,
initial.commit09911bf2008-07-26 23:55:29139 IconLoader::IconSize size)
[email protected]0f38ceae2009-05-08 19:01:02140 : group(group),
initial.commit09911bf2008-07-26 23:55:29141 size(size) {
142}
143
144bool IconManager::CacheKey::operator<(const CacheKey &other) const {
[email protected]0f38ceae2009-05-08 19:01:02145 if (group != other.group)
146 return group < other.group;
initial.commit09911bf2008-07-26 23:55:29147 return size < other.size;
148}