icon_manager.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/file_util.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/task_runner.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RunCallbackIfNotCanceled( 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CancelableTaskTracker::IsCanceledCallback& is_canceled, 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const IconManager::IconRequestCallback& callback, 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Image* image) { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_canceled.Run()) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(image); 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IconManager::ClientRequest { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IconRequestCallback callback; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconGroupID group; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconLoader::IconSize size; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IconManager::IconManager() { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IconManager::~IconManager() { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteValues(&icon_cache_); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Image* IconManager::LookupIcon(const base::FilePath& file_name, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconLoader::IconSize size) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconGroupID group = GetGroupIDFromFilepath(file_name); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconMap::iterator it = icon_cache_.find(CacheKey(group, size)); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != icon_cache_.end()) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->second; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CancelableTaskTracker::TaskId IconManager::LoadIcon( 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& file_name, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconLoader::IconSize size, 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const IconRequestCallback& callback, 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableTaskTracker* tracker) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconGroupID group = GetGroupIDFromFilepath(file_name); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconLoader* loader = new IconLoader(group, size, this); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loader->AddRef(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loader->Start(); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableTaskTracker::IsCanceledCallback is_canceled; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableTaskTracker::TaskId id = tracker->NewTrackedTaskId(&is_canceled); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IconRequestCallback callback_runner = base::Bind( 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &RunCallbackIfNotCanceled, is_canceled, callback); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientRequest client_request = { callback_runner, group, size }; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requests_[loader] = client_request; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return id; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IconLoader::Delegate implementation ----------------------------------------- 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IconManager::OnImageLoaded(IconLoader* loader, gfx::Image* result) { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientRequests::iterator rit = requests_.find(loader); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Balances the AddRef() in LoadIcon(). 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loader->Release(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Look up our client state. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rit == requests_.end()) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Return false to indicate result should be deleted. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ClientRequest& client_request = rit->second; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cache the bitmap. Watch out: |result| or the cached bitmap may be NULL to 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // indicate a current or past failure. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CacheKey key(client_request.group, client_request.size); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconMap::iterator it = icon_cache_.find(key); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != icon_cache_.end() && result && it->second) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->second->SwapRepresentations(result); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete result; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = it->second; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_cache_[key] = result; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inform our client that the request has completed. 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_request.callback.Run(result); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requests_.erase(rit); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; // Indicates we took ownership of result. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IconManager::CacheKey::CacheKey(const IconGroupID& group, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconLoader::IconSize size) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : group(group), 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size(size) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IconManager::CacheKey::operator<(const CacheKey &other) const { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (group != other.group) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return group < other.group; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size < other.size; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 118