icon_manager.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/icon_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/task_runner.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RunCallbackIfNotCanceled( 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const IconManager::IconRequestCallback& callback, 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Image* image) { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_canceled.Run()) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(image); 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IconManager::ClientRequest { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IconRequestCallback callback; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath file_path; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconLoader::IconSize size; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IconManager::IconManager() { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IconManager::~IconManager() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteValues(&icon_cache_); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Image* IconManager::LookupIconFromFilepath(const base::FilePath& file_name, 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IconLoader::IconSize size) { 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GroupMap::iterator it = group_cache_.find(file_name); 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (it != group_cache_.end()) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return LookupIconFromGroup(it->second, size); 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return NULL; 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Image* IconManager::LookupIconFromGroup(const IconGroupID& group, 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IconLoader::IconSize size) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconMap::iterator it = icon_cache_.find(CacheKey(group, size)); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != icon_cache_.end()) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->second; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId IconManager::LoadIcon( 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& file_name, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconLoader::IconSize size, 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const IconRequestCallback& callback, 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker* tracker) { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IconLoader* loader = new IconLoader(file_name, size, this); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loader->AddRef(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loader->Start(); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker::IsCanceledCallback is_canceled; 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker::TaskId id = 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tracker->NewTrackedTaskId(&is_canceled); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IconRequestCallback callback_runner = base::Bind( 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &RunCallbackIfNotCanceled, is_canceled, callback); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ClientRequest client_request = { callback_runner, file_name, size }; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requests_[loader] = client_request; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return id; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IconLoader::Delegate implementation ----------------------------------------- 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IconManager::OnGroupLoaded(IconLoader* loader, 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const IconGroupID& group) { 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ClientRequests::iterator rit = requests_.find(loader); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (rit == requests_.end()) { 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Image* result = LookupIconFromGroup(group, rit->second.size); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!result) { 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return OnImageLoaded(loader, result, group); 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IconManager::OnImageLoaded( 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IconLoader* loader, gfx::Image* result, const IconGroupID& group) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientRequests::iterator rit = requests_.find(loader); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Balances the AddRef() in LoadIcon(). 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loader->Release(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Look up our client state. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rit == requests_.end()) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Return false to indicate result should be deleted. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ClientRequest& client_request = rit->second; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Cache the bitmap. Watch out: |result| may be NULL to indicate a current 1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // failure. We assume that if we have an entry in |icon_cache_| 1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // it must not be NULL. 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CacheKey key(group, client_request.size); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconMap::iterator it = icon_cache_.find(key); 1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (it != icon_cache_.end()) { 1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!result) { 1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) delete it->second; 1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) icon_cache_.erase(it); 1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else if (result != it->second) { 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it->second->SwapRepresentations(result); 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete result; 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result = it->second; 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else if (result) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_cache_[key] = result; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) group_cache_[client_request.file_path] = group; 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inform our client that the request has completed. 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_request.callback.Run(result); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requests_.erase(rit); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; // Indicates we took ownership of result. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IconManager::CacheKey::CacheKey(const IconGroupID& group, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconLoader::IconSize size) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : group(group), 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size(size) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IconManager::CacheKey::operator<(const CacheKey &other) const { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (group != other.group) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return group < other.group; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size < other.size; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 149