Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / icon_manager.cc
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/icon_manager.h"
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/stl_util.h"
10 #include "base/task_runner.h"
11 #include "third_party/skia/include/core/SkBitmap.h"
12 #include "third_party/skia/include/core/SkCanvas.h"
13
14 namespace {
15
16 void RunCallbackIfNotCanceled(
17     const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
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
27 struct IconManager::ClientRequest {
28   IconRequestCallback callback;
29   base::FilePath file_path;
30   IconLoader::IconSize size;
31 };
32
33 IconManager::IconManager() {
34 }
35
36 IconManager::~IconManager() {
37   STLDeleteValues(&icon_cache_);
38 }
39
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) {
51   IconMap::iterator it = icon_cache_.find(CacheKey(group, size));
52   if (it != icon_cache_.end())
53     return it->second;
54
55   return NULL;
56 }
57
58 base::CancelableTaskTracker::TaskId IconManager::LoadIcon(
59     const base::FilePath& file_name,
60     IconLoader::IconSize size,
61     const IconRequestCallback& callback,
62     base::CancelableTaskTracker* tracker) {
63   IconLoader* loader = new IconLoader(file_name, size, this);
64   loader->AddRef();
65   loader->Start();
66
67   base::CancelableTaskTracker::IsCanceledCallback is_canceled;
68   base::CancelableTaskTracker::TaskId id =
69       tracker->NewTrackedTaskId(&is_canceled);
70   IconRequestCallback callback_runner = base::Bind(
71       &RunCallbackIfNotCanceled, is_canceled, callback);
72
73   ClientRequest client_request = { callback_runner, file_name, size };
74   requests_[loader] = client_request;
75   return id;
76 }
77
78 // IconLoader::Delegate implementation -----------------------------------------
79
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) {
98   ClientRequests::iterator rit = requests_.find(loader);
99
100   // Balances the AddRef() in LoadIcon().
101   loader->Release();
102
103   // Look up our client state.
104   if (rit == requests_.end()) {
105     NOTREACHED();
106     return false;  // Return false to indicate result should be deleted.
107   }
108
109   const ClientRequest& client_request = rit->second;
110
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.
114   CacheKey key(group, client_request.size);
115   IconMap::iterator it = icon_cache_.find(key);
116   if (it != icon_cache_.end()) {
117     if (!result) {
118       delete it->second;
119       icon_cache_.erase(it);
120     } else if (result != it->second) {
121       it->second->SwapRepresentations(result);
122       delete result;
123       result = it->second;
124     }
125   } else if (result) {
126     icon_cache_[key] = result;
127   }
128
129   group_cache_[client_request.file_path] = group;
130
131   // Inform our client that the request has completed.
132   client_request.callback.Run(result);
133   requests_.erase(rit);
134
135   return true;  // Indicates we took ownership of result.
136 }
137
138 IconManager::CacheKey::CacheKey(const IconGroupID& group,
139                                 IconLoader::IconSize size)
140     : group(group),
141       size(size) {
142 }
143
144 bool IconManager::CacheKey::operator<(const CacheKey &other) const {
145   if (group != other.group)
146     return group < other.group;
147   return size < other.size;
148 }