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