[email protected] | 66171ab | 2011-03-03 15:50:07 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
| 5 | #include "chrome/browser/icon_manager.h" |
| 6 | |
jsbell | 50f0e75 | 2015-11-16 19:36:53 | [diff] [blame^] | 7 | #include <tuple> |
| 8 | |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 9 | #include "base/bind.h" |
[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame] | 10 | #include "base/memory/scoped_ptr.h" |
[email protected] | 7286e3fc | 2011-07-19 22:13:24 | [diff] [blame] | 11 | #include "base/stl_util.h" |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 12 | #include "base/task_runner.h" |
[email protected] | c43c668 | 2009-05-19 14:51:44 | [diff] [blame] | 13 | #include "third_party/skia/include/core/SkBitmap.h" |
| 14 | #include "third_party/skia/include/core/SkCanvas.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 15 | |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 16 | namespace { |
| 17 | |
| 18 | void RunCallbackIfNotCanceled( |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 19 | const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 20 | 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] | 38e0898 | 2010-10-22 17:28:43 | [diff] [blame] | 29 | struct IconManager::ClientRequest { |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 30 | IconRequestCallback callback; |
[email protected] | bc0147b | 2013-04-03 20:50:59 | [diff] [blame] | 31 | base::FilePath file_path; |
[email protected] | 38e0898 | 2010-10-22 17:28:43 | [diff] [blame] | 32 | IconLoader::IconSize size; |
| 33 | }; |
| 34 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 35 | IconManager::IconManager() { |
| 36 | } |
| 37 | |
| 38 | IconManager::~IconManager() { |
| 39 | STLDeleteValues(&icon_cache_); |
| 40 | } |
| 41 | |
[email protected] | bc0147b | 2013-04-03 20:50:59 | [diff] [blame] | 42 | gfx::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 | |
| 51 | gfx::Image* IconManager::LookupIconFromGroup(const IconGroupID& group, |
| 52 | IconLoader::IconSize size) { |
[email protected] | 0f38ceae | 2009-05-08 19:01:02 | [diff] [blame] | 53 | IconMap::iterator it = icon_cache_.find(CacheKey(group, size)); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 54 | if (it != icon_cache_.end()) |
| 55 | return it->second; |
| 56 | |
| 57 | return NULL; |
| 58 | } |
| 59 | |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 60 | base::CancelableTaskTracker::TaskId IconManager::LoadIcon( |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 61 | const base::FilePath& file_name, |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 62 | IconLoader::IconSize size, |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 63 | const IconRequestCallback& callback, |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 64 | base::CancelableTaskTracker* tracker) { |
[email protected] | bc0147b | 2013-04-03 20:50:59 | [diff] [blame] | 65 | IconLoader* loader = new IconLoader(file_name, size, this); |
[email protected] | 46728b1f | 2009-05-07 20:42:24 | [diff] [blame] | 66 | loader->AddRef(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 67 | loader->Start(); |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 68 | |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 69 | base::CancelableTaskTracker::IsCanceledCallback is_canceled; |
| 70 | base::CancelableTaskTracker::TaskId id = |
| 71 | tracker->NewTrackedTaskId(&is_canceled); |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 72 | IconRequestCallback callback_runner = base::Bind( |
| 73 | &RunCallbackIfNotCanceled, is_canceled, callback); |
| 74 | |
[email protected] | bc0147b | 2013-04-03 20:50:59 | [diff] [blame] | 75 | ClientRequest client_request = { callback_runner, file_name, size }; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 76 | requests_[loader] = client_request; |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 77 | return id; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 78 | } |
| 79 | |
| 80 | // IconLoader::Delegate implementation ----------------------------------------- |
| 81 | |
[email protected] | bc0147b | 2013-04-03 20:50:59 | [diff] [blame] | 82 | bool 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 | |
| 98 | bool IconManager::OnImageLoaded( |
| 99 | IconLoader* loader, gfx::Image* result, const IconGroupID& group) { |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 100 | ClientRequests::iterator rit = requests_.find(loader); |
| 101 | |
[email protected] | 46728b1f | 2009-05-07 20:42:24 | [diff] [blame] | 102 | // Balances the AddRef() in LoadIcon(). |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 103 | loader->Release(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 104 | |
| 105 | // Look up our client state. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 106 | if (rit == requests_.end()) { |
| 107 | NOTREACHED(); |
[email protected] | cf2ef75 | 2008-09-11 21:19:29 | [diff] [blame] | 108 | return false; // Return false to indicate result should be deleted. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 109 | } |
| 110 | |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 111 | const ClientRequest& client_request = rit->second; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 112 | |
[email protected] | 0204a78 | 2013-10-24 03:18:59 | [diff] [blame] | 113 | // 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] | bc0147b | 2013-04-03 20:50:59 | [diff] [blame] | 116 | CacheKey key(group, client_request.size); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 117 | IconMap::iterator it = icon_cache_.find(key); |
[email protected] | 0204a78 | 2013-10-24 03:18:59 | [diff] [blame] | 118 | 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] | bc0147b | 2013-04-03 20:50:59 | [diff] [blame] | 123 | it->second->SwapRepresentations(result); |
| 124 | delete result; |
| 125 | result = it->second; |
| 126 | } |
[email protected] | 0204a78 | 2013-10-24 03:18:59 | [diff] [blame] | 127 | } else if (result) { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 128 | icon_cache_[key] = result; |
| 129 | } |
| 130 | |
[email protected] | bc0147b | 2013-04-03 20:50:59 | [diff] [blame] | 131 | group_cache_[client_request.file_path] = group; |
| 132 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 133 | // Inform our client that the request has completed. |
[email protected] | c189698 | 2012-12-05 20:26:17 | [diff] [blame] | 134 | client_request.callback.Run(result); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 135 | requests_.erase(rit); |
| 136 | |
[email protected] | cf2ef75 | 2008-09-11 21:19:29 | [diff] [blame] | 137 | return true; // Indicates we took ownership of result. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 138 | } |
| 139 | |
[email protected] | 0f38ceae | 2009-05-08 19:01:02 | [diff] [blame] | 140 | IconManager::CacheKey::CacheKey(const IconGroupID& group, |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 141 | IconLoader::IconSize size) |
[email protected] | 0f38ceae | 2009-05-08 19:01:02 | [diff] [blame] | 142 | : group(group), |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 143 | size(size) { |
| 144 | } |
| 145 | |
| 146 | bool IconManager::CacheKey::operator<(const CacheKey &other) const { |
jsbell | 50f0e75 | 2015-11-16 19:36:53 | [diff] [blame^] | 147 | return std::tie(group, size) < std::tie(other.group, other.size); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 148 | } |