1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/icon_manager.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/stl_util-inl.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkCanvas.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstruct IconManager::ClientRequest {
14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<IconRequest> request;
15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  IconGroupID group;
16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  IconLoader::IconSize size;
17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch};
18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochIconManager::IconManager() {
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochIconManager::~IconManager() {
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  STLDeleteValues(&icon_cache_);
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsengfx::Image* IconManager::LookupIcon(const FilePath& file_name,
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    IconLoader::IconSize size) {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  IconGroupID group = GetGroupIDFromFilepath(file_name);
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  IconMap::iterator it = icon_cache_.find(CacheKey(group, size));
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it != icon_cache_.end())
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return it->second;
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochIconManager::Handle IconManager::LoadIcon(
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FilePath& file_name,
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    IconLoader::IconSize size,
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CancelableRequestConsumerBase* consumer,
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    IconRequestCallback* callback) {
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  IconGroupID group = GetGroupIDFromFilepath(file_name);
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  IconRequest* request = new IconRequest(callback);
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddRequest(request, consumer);
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  IconLoader* loader = new IconLoader(group, size, this);
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  loader->AddRef();
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  loader->Start();
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ClientRequest client_request = { request, group, size };
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  requests_[loader] = client_request;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return request->handle();
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// IconLoader::Delegate implementation -----------------------------------------
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool IconManager::OnImageLoaded(IconLoader* source, gfx::Image* result) {
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ClientRequests::iterator rit = requests_.find(source);
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Balances the AddRef() in LoadIcon().
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  source->Release();
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Look up our client state.
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rit == requests_.end()) {
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // Return false to indicate result should be deleted.
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ClientRequest client_request = rit->second;
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (client_request.request->canceled()) {
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    requests_.erase(rit);
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // Return false to indicate result should be deleted.
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cache the bitmap. Watch out: |result| or the cached bitmap may be NULL to
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // indicate a current or past failure.
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CacheKey key(client_request.group, client_request.size);
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  IconMap::iterator it = icon_cache_.find(key);
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it != icon_cache_.end() && result && it->second) {
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    it->second->SwapRepresentations(result);
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete result;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result = it->second;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    icon_cache_[key] = result;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Inform our client that the request has completed.
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  IconRequest* icon_request = client_request.request;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  icon_request->ForwardResult(IconRequest::TupleType(icon_request->handle(),
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                     result));
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  requests_.erase(rit);
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;  // Indicates we took ownership of result.
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochIconManager::CacheKey::CacheKey(const IconGroupID& group,
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                IconLoader::IconSize size)
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : group(group),
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size(size) {
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IconManager::CacheKey::operator<(const CacheKey &other) const {
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (group != other.group)
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return group < other.group;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return size < other.size;
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
104