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