Update icon loading API implementation

This commit is contained in:
Yury Solovyov 2017-02-16 22:19:19 +03:00
parent 19b686c90b
commit 977abc6458
9 changed files with 176 additions and 243 deletions

View file

@ -890,15 +890,18 @@ void App::GetFileIcon(const base::FilePath& path,
return; return;
} }
IconManager* icon_manager = IconManager::GetInstance(); if (!icon_manager_.get()) {
gfx::Image* icon = icon_manager->LookupIconFromFilepath(normalized_path, icon_manager_.reset(new IconManager());
}
gfx::Image* icon = icon_manager_->LookupIconFromFilepath(normalized_path,
icon_size); icon_size);
if (icon) { if (icon) {
callback.Run(v8::Null(isolate()), *icon); callback.Run(v8::Null(isolate()), *icon);
} else { } else {
icon_manager->LoadIcon(normalized_path, icon_size, icon_manager_->LoadIcon(normalized_path, icon_size,
base::Bind(&OnIconDataAvailable, isolate(), base::Bind(&OnIconDataAvailable, isolate(),
callback)); callback), &cancelable_task_tracker_);
} }
} }

View file

@ -13,7 +13,8 @@
#include "atom/browser/browser.h" #include "atom/browser/browser.h"
#include "atom/browser/browser_observer.h" #include "atom/browser/browser_observer.h"
#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/callback.h"
#include "chrome/browser/icon_loader.h" #include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/icon_manager.h"
#include "chrome/browser/process_singleton.h" #include "chrome/browser/process_singleton.h"
#include "content/public/browser/gpu_data_manager_observer.h" #include "content/public/browser/gpu_data_manager_observer.h"
#include "native_mate/handle.h" #include "native_mate/handle.h"
@ -129,6 +130,8 @@ class App : public AtomBrowserClient::Delegate,
void DisableHardwareAcceleration(mate::Arguments* args); void DisableHardwareAcceleration(mate::Arguments* args);
bool IsAccessibilitySupportEnabled(); bool IsAccessibilitySupportEnabled();
Browser::LoginItemSettings GetLoginItemSettings(mate::Arguments* args); Browser::LoginItemSettings GetLoginItemSettings(mate::Arguments* args);
base::CancelableTaskTracker cancelable_task_tracker_;
std::unique_ptr<IconManager> icon_manager_;
#if defined(USE_NSS_CERTS) #if defined(USE_NSS_CERTS)
void ImportCertificate(const base::DictionaryValue& options, void ImportCertificate(const base::DictionaryValue& options,
const net::CompletionCallback& callback); const net::CompletionCallback& callback);

View file

@ -3,46 +3,40 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/icon_loader.h" #include "chrome/browser/icon_loader.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
using content::BrowserThread; using content::BrowserThread;
IconLoader::IconLoader(const base::FilePath& file_path, // static
IconSize size, IconLoader* IconLoader::Create(const base::FilePath& file_path,
Delegate* delegate) IconSize size,
: target_task_runner_(NULL), IconLoadedCallback callback) {
file_path_(file_path), return new IconLoader(file_path, size, callback);
icon_size_(size), }
delegate_(delegate) {}
IconLoader::~IconLoader() {}
void IconLoader::Start() { void IconLoader::Start() {
target_task_runner_ = base::ThreadTaskRunnerHandle::Get(); target_task_runner_ = base::ThreadTaskRunnerHandle::Get();
BrowserThread::PostTaskAndReply(
BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE, BrowserThread::FILE, FROM_HERE,
base::Bind(&IconLoader::ReadGroup, this), base::Bind(&IconLoader::ReadGroup, base::Unretained(this)),
base::Bind(&IconLoader::OnReadGroup, this)); base::Bind(&IconLoader::OnReadGroup, base::Unretained(this)));
} }
IconLoader::IconLoader(const base::FilePath& file_path,
IconSize size,
IconLoadedCallback callback)
: file_path_(file_path), icon_size_(size), callback_(callback) {}
IconLoader::~IconLoader() {}
void IconLoader::ReadGroup() { void IconLoader::ReadGroup() {
group_ = ReadGroupIDFromFilepath(file_path_); group_ = GroupForFilepath(file_path_);
} }
void IconLoader::OnReadGroup() { void IconLoader::OnReadGroup() {
if (IsIconMutableFromFilepath(file_path_) || BrowserThread::PostTask(
!delegate_->OnGroupLoaded(this, group_)) { ReadIconThreadID(), FROM_HERE,
BrowserThread::PostTask(ReadIconThreadID(), FROM_HERE, base::Bind(&IconLoader::ReadIcon, base::Unretained(this)));
base::Bind(&IconLoader::ReadIcon, this));
}
}
void IconLoader::NotifyDelegate() {
// If the delegate takes ownership of the Image, release it from the scoped
// pointer.
if (delegate_->OnImageLoaded(this, image_.get(), group_))
ignore_result(image_.release()); // Can't ignore return value.
} }

View file

@ -8,31 +8,30 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "base/callback.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "ui/gfx/image/image.h" #include "ui/gfx/image/image.h"
#if defined(OS_WIN)
// On Windows, we group files by their extension, with several exceptions:
// .dll, .exe, .ico. See IconManager.h for explanation.
typedef std::wstring IconGroupID;
#elif defined(OS_POSIX)
// On POSIX, we group files by MIME type.
typedef std::string IconGroupID;
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// //
// A facility to read a file containing an icon asynchronously in the IO // A facility to read a file containing an icon asynchronously in the IO
// thread. Returns the icon in the form of an ImageSkia. // thread. Returns the icon in the form of an ImageSkia.
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class IconLoader : public base::RefCountedThreadSafe<IconLoader> { class IconLoader {
public: public:
// An IconGroup is a class of files that all share the same icon. For all
// platforms but Windows, and for most files on Windows, it is the file type
// (e.g. all .mp3 files share an icon, all .html files share an icon). On
// Windows, for certain file types (.exe, .dll, etc), each file of that type
// is assumed to have a unique icon. In that case, each of those files is a
// group to itself.
using IconGroup = base::FilePath::StringType;
enum IconSize { enum IconSize {
SMALL = 0, // 16x16 SMALL = 0, // 16x16
NORMAL, // 32x32 NORMAL, // 32x32
@ -40,42 +39,32 @@ class IconLoader : public base::RefCountedThreadSafe<IconLoader> {
ALL, // All sizes available ALL, // All sizes available
}; };
class Delegate { // The callback invoked when an icon has been read. The parameters are:
public: // - The icon that was loaded, or null if there was a failure to load it.
// Invoked when an icon group has been read, but before the icon data // - The determined group from the original requested path.
// is read. If the icon is already cached, this method should call and using IconLoadedCallback =
// return the results of OnImageLoaded with the cached image. base::Callback<void(std::unique_ptr<gfx::Image>, const IconGroup&)>;
virtual bool OnGroupLoaded(IconLoader* source,
const IconGroupID& group) = 0;
// Invoked when an icon has been read. |source| is the IconLoader. If the
// icon has been successfully loaded, result is non-null. This method must
// return true if it is taking ownership of the returned image.
virtual bool OnImageLoaded(IconLoader* source,
gfx::Image* result,
const IconGroupID& group) = 0;
protected: // Creates an IconLoader, which owns itself. If the IconLoader might outlive
virtual ~Delegate() {} // the caller, be sure to use a weak pointer in the |callback|.
}; static IconLoader* Create(const base::FilePath& file_path,
IconSize size,
IconLoadedCallback callback);
IconLoader(const base::FilePath& file_path, // Starts the process of reading the icon. When the reading of the icon is
IconSize size, // complete, the IconLoadedCallback callback will be fulfilled, and the
Delegate* delegate); // IconLoader will delete itself.
// Start reading the icon on the file thread.
void Start(); void Start();
private: private:
friend class base::RefCountedThreadSafe<IconLoader>; IconLoader(const base::FilePath& file_path,
IconSize size,
IconLoadedCallback callback);
virtual ~IconLoader(); ~IconLoader();
// Get the identifying string for the given file. The implementation // Given a file path, get the group for the given file.
// is in icon_loader_[platform].cc. static IconGroup GroupForFilepath(const base::FilePath& file_path);
static IconGroupID ReadGroupIDFromFilepath(const base::FilePath& path);
// Some icons (exe's on windows) can change as they're loaded.
static bool IsIconMutableFromFilepath(const base::FilePath& path);
// The thread ReadIcon() should be called on. // The thread ReadIcon() should be called on.
static content::BrowserThread::ID ReadIconThreadID(); static content::BrowserThread::ID ReadIconThreadID();
@ -84,20 +73,18 @@ class IconLoader : public base::RefCountedThreadSafe<IconLoader> {
void OnReadGroup(); void OnReadGroup();
void ReadIcon(); void ReadIcon();
void NotifyDelegate();
// The task runner object of the thread in which we notify the delegate. // The task runner object of the thread in which we notify the delegate.
scoped_refptr<base::SingleThreadTaskRunner> target_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> target_task_runner_;
base::FilePath file_path_; base::FilePath file_path_;
IconGroupID group_; IconGroup group_;
IconSize icon_size_; IconSize icon_size_;
std::unique_ptr<gfx::Image> image_; std::unique_ptr<gfx::Image> image_;
Delegate* delegate_; IconLoadedCallback callback_;
DISALLOW_COPY_AND_ASSIGN(IconLoader); DISALLOW_COPY_AND_ASSIGN(IconLoader);
}; };

View file

@ -10,14 +10,9 @@
#include "ui/views/linux_ui/linux_ui.h" #include "ui/views/linux_ui/linux_ui.h"
// static // static
IconGroupID IconLoader::ReadGroupIDFromFilepath( IconLoader::IconGroup IconLoader::GroupForFilepath(
const base::FilePath& filepath) { const base::FilePath& file_path) {
return base::nix::GetFileMimeType(filepath); return base::nix::GetFileMimeType(file_path);
}
// static
bool IconLoader::IsIconMutableFromFilepath(const base::FilePath&) {
return false;
} }
// static // static
@ -50,6 +45,7 @@ void IconLoader::ReadIcon() {
image_.reset(new gfx::Image(image)); image_.reset(new gfx::Image(image));
} }
target_task_runner_->PostTask(FROM_HERE, target_task_runner_->PostTask(
base::Bind(&IconLoader::NotifyDelegate, this)); FROM_HERE, base::Bind(callback_, base::Passed(&image_), group_));
delete this;
} }

View file

@ -15,14 +15,9 @@
#include "ui/gfx/image/image_skia_util_mac.h" #include "ui/gfx/image/image_skia_util_mac.h"
// static // static
IconGroupID IconLoader::ReadGroupIDFromFilepath( IconLoader::IconGroup IconLoader::GroupForFilepath(
const base::FilePath& filepath) { const base::FilePath& file_path) {
return filepath.Extension(); return file_path.Extension();
}
// static
bool IconLoader::IsIconMutableFromFilepath(const base::FilePath&) {
return false;
} }
// static // static
@ -57,6 +52,7 @@ void IconLoader::ReadIcon() {
} }
} }
target_task_runner_->PostTask(FROM_HERE, target_task_runner_->PostTask(
base::Bind(&IconLoader::NotifyDelegate, this)); FROM_HERE, base::Bind(callback_, base::Passed(&image_), group_));
delete this;
} }

View file

@ -17,18 +17,15 @@
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
// static // static
IconGroupID IconLoader::ReadGroupIDFromFilepath( IconLoader::IconGroup IconLoader::GroupForFilepath(
const base::FilePath& filepath) { const base::FilePath& file_path) {
if (!IsIconMutableFromFilepath(filepath)) if (file_path.MatchesExtension(L".exe") ||
return filepath.Extension(); file_path.MatchesExtension(L".dll") ||
return filepath.value(); file_path.MatchesExtension(L".ico")) {
} return file_path.value();
}
// static return file_path.Extension();
bool IconLoader::IsIconMutableFromFilepath(const base::FilePath& filepath) {
return filepath.MatchesExtension(L".exe") ||
filepath.MatchesExtension(L".dll") ||
filepath.MatchesExtension(L".ico");
} }
// static // static
@ -54,22 +51,22 @@ void IconLoader::ReadIcon() {
image_.reset(); image_.reset();
SHFILEINFO file_info = {0}; SHFILEINFO file_info = { 0 };
if (SHGetFileInfo(group_.c_str(), FILE_ATTRIBUTE_NORMAL, &file_info, if (SHGetFileInfo(group_.c_str(), FILE_ATTRIBUTE_NORMAL, &file_info,
sizeof(SHFILEINFO), sizeof(SHFILEINFO),
SHGFI_ICON | size | SHGFI_USEFILEATTRIBUTES)) { SHGFI_ICON | size | SHGFI_USEFILEATTRIBUTES)) {
std::unique_ptr<SkBitmap> bitmap( std::unique_ptr<SkBitmap> bitmap(
IconUtil::CreateSkBitmapFromHICON(file_info.hIcon)); IconUtil::CreateSkBitmapFromHICON(file_info.hIcon));
if (bitmap.get()) { if (bitmap.get()) {
gfx::ImageSkia image_skia( gfx::ImageSkia image_skia(gfx::ImageSkiaRep(*bitmap,
gfx::ImageSkiaRep(*bitmap, display::win::GetDPIScale())); display::win::GetDPIScale()));
image_skia.MakeThreadSafe(); image_skia.MakeThreadSafe();
image_.reset(new gfx::Image(image_skia)); image_.reset(new gfx::Image(image_skia));
DestroyIcon(file_info.hIcon); DestroyIcon(file_info.hIcon);
} }
} }
// Always notify the delegate, regardless of success. target_task_runner_->PostTask(
target_task_runner_->PostTask(FROM_HERE, FROM_HERE, base::Bind(callback_, base::Passed(&image_), group_));
base::Bind(&IconLoader::NotifyDelegate, this)); delete this;
} }

View file

@ -8,121 +8,86 @@
#include <tuple> #include <tuple>
#include "base/bind.h" #include "base/bind.h"
#include "base/stl_util.h"
#include "base/task_runner.h" #include "base/task_runner.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkCanvas.h"
struct IconManager::ClientRequest { namespace {
IconRequestCallback callback;
base::FilePath file_path;
IconLoader::IconSize size;
};
// static void RunCallbackIfNotCanceled(
IconManager* IconManager::GetInstance() { const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
return base::Singleton<IconManager>::get(); const IconManager::IconRequestCallback& callback,
gfx::Image* image) {
if (is_canceled.Run())
return;
callback.Run(image);
} }
IconManager::IconManager() {} } // namespace
IconManager::IconManager() : weak_factory_(this) {}
IconManager::~IconManager() { IconManager::~IconManager() {
base::STLDeleteValues(&icon_cache_);
} }
gfx::Image* IconManager::LookupIconFromFilepath(const base::FilePath& file_name, gfx::Image* IconManager::LookupIconFromFilepath(const base::FilePath& file_path,
IconLoader::IconSize size) { IconLoader::IconSize size) {
GroupMap::iterator it = group_cache_.find(file_name); auto group_it = group_cache_.find(file_path);
if (it != group_cache_.end()) if (group_it == group_cache_.end())
return LookupIconFromGroup(it->second, size); return nullptr;
return NULL; CacheKey key(group_it->second, size);
auto icon_it = icon_cache_.find(key);
if (icon_it == icon_cache_.end())
return nullptr;
return icon_it->second.get();
} }
gfx::Image* IconManager::LookupIconFromGroup(const IconGroupID& group, base::CancelableTaskTracker::TaskId IconManager::LoadIcon(
IconLoader::IconSize size) { const base::FilePath& file_path,
IconMap::iterator it = icon_cache_.find(CacheKey(group, size)); IconLoader::IconSize size,
if (it != icon_cache_.end()) const IconRequestCallback& callback,
return it->second; base::CancelableTaskTracker* tracker) {
base::CancelableTaskTracker::IsCanceledCallback is_canceled;
base::CancelableTaskTracker::TaskId id =
tracker->NewTrackedTaskId(&is_canceled);
IconRequestCallback callback_runner = base::Bind(
&RunCallbackIfNotCanceled, is_canceled, callback);
return nullptr; IconLoader* loader = IconLoader::Create(
} file_path, size,
base::Bind(&IconManager::OnIconLoaded, weak_factory_.GetWeakPtr(),
void IconManager::LoadIcon(const base::FilePath& file_name, callback_runner, file_path, size));
IconLoader::IconSize size,
const IconRequestCallback& callback) {
IconLoader* loader = new IconLoader(file_name, size, this);
loader->AddRef();
loader->Start(); loader->Start();
ClientRequest client_request = {callback, file_name, size}; return id;
requests_[loader] = client_request;
} }
// IconLoader::Delegate implementation ----------------------------------------- void IconManager::OnIconLoaded(IconRequestCallback callback,
base::FilePath file_path,
bool IconManager::OnGroupLoaded(IconLoader* loader, const IconGroupID& group) { IconLoader::IconSize size,
ClientRequests::iterator rit = requests_.find(loader); std::unique_ptr<gfx::Image> result,
if (rit == requests_.end()) { const IconLoader::IconGroup& group) {
NOTREACHED(); // Cache the bitmap. Watch out: |result| may be null, which indicates a
return false; // failure. We assume that if we have an entry in |icon_cache_| it must not be
// null.
CacheKey key(group, size);
if (result) {
callback.Run(result.get());
icon_cache_[key] = std::move(result);
} else {
callback.Run(nullptr);
icon_cache_.erase(key);
} }
gfx::Image* result = LookupIconFromGroup(group, rit->second.size); group_cache_[file_path] = group;
if (!result) {
return false;
}
return OnImageLoaded(loader, result, group);
} }
bool IconManager::OnImageLoaded(IconLoader* loader, IconManager::CacheKey::CacheKey(const IconLoader::IconGroup& group,
gfx::Image* result,
const IconGroupID& group) {
ClientRequests::iterator rit = requests_.find(loader);
// Balances the AddRef() in LoadIcon().
loader->Release();
// Look up our client state.
if (rit == requests_.end()) {
NOTREACHED();
return false; // Return false to indicate result should be deleted.
}
const ClientRequest& client_request = rit->second;
// Cache the bitmap. Watch out: |result| may be NULL to indicate a current
// failure. We assume that if we have an entry in |icon_cache_|
// it must not be NULL.
CacheKey key(group, client_request.size);
IconMap::iterator it = icon_cache_.find(key);
if (it != icon_cache_.end()) {
if (!result) {
delete it->second;
icon_cache_.erase(it);
} else if (result != it->second) {
it->second->SwapRepresentations(result);
delete result;
result = it->second;
}
} else if (result) {
icon_cache_[key] = result;
}
group_cache_[client_request.file_path] = group;
// Inform our client that the request has completed.
client_request.callback.Run(result);
requests_.erase(rit);
return true; // Indicates we took ownership of result.
}
IconManager::CacheKey::CacheKey(const IconGroupID& group,
IconLoader::IconSize size) IconLoader::IconSize size)
: group(group), size(size) {} : group(group), size(size) {}
bool IconManager::CacheKey::operator<(const CacheKey& other) const { bool IconManager::CacheKey::operator<(const CacheKey &other) const {
return std::tie(group, size) < std::tie(other.group, other.size); return std::tie(group, size) < std::tie(other.group, other.size);
} }

View file

@ -34,7 +34,7 @@
// 2. An asynchronous icon load from a file on the file thread: // 2. An asynchronous icon load from a file on the file thread:
// IconManager::LoadIcon() // IconManager::LoadIcon()
// //
// When using the second (asychronous) method, callers must supply a callback // When using the second (asynchronous) method, callers must supply a callback
// which will be run once the icon has been extracted. The icon manager will // which will be run once the icon has been extracted. The icon manager will
// cache the results of the icon extraction so that subsequent lookups will be // cache the results of the icon extraction so that subsequent lookups will be
// fast. // fast.
@ -46,25 +46,29 @@
#define CHROME_BROWSER_ICON_MANAGER_H_ #define CHROME_BROWSER_ICON_MANAGER_H_
#include <map> #include <map>
#include <memory>
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/singleton.h" #include "base/memory/weak_ptr.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/icon_loader.h" #include "chrome/browser/icon_loader.h"
#include "ui/gfx/image/image.h" #include "ui/gfx/image/image.h"
class IconManager : public IconLoader::Delegate { class IconManager {
public: public:
static IconManager* GetInstance(); IconManager();
~IconManager();
// Synchronous call to examine the internal caches for the icon. Returns the // Synchronous call to examine the internal caches for the icon. Returns the
// icon if we have already loaded it, NULL if we don't have it and must load // icon if we have already loaded it, or null if we don't have it and must
// it via 'LoadIcon'. The returned bitmap is owned by the IconManager and must // load it via LoadIcon(). The returned bitmap is owned by the IconManager and
// not be free'd by the caller. If the caller needs to modify the icon, it // must not be free'd by the caller. If the caller needs to modify the icon,
// must make a copy and modify the copy. // it must make a copy and modify the copy.
gfx::Image* LookupIconFromFilepath(const base::FilePath& file_name, gfx::Image* LookupIconFromFilepath(const base::FilePath& file_path,
IconLoader::IconSize size); IconLoader::IconSize size);
typedef base::Callback<void(gfx::Image*)> IconRequestCallback; using IconRequestCallback = base::Callback<void(gfx::Image*)>;
// Asynchronous call to lookup and return the icon associated with file. The // Asynchronous call to lookup and return the icon associated with file. The
// work is done on the file thread, with the callbacks running on the thread // work is done on the file thread, with the callbacks running on the thread
@ -74,47 +78,35 @@ class IconManager : public IconLoader::Delegate {
// 1. This does *not* check the cache. // 1. This does *not* check the cache.
// 2. The returned bitmap pointer is *not* owned by callback. So callback // 2. The returned bitmap pointer is *not* owned by callback. So callback
// should never keep it or delete it. // should never keep it or delete it.
// 3. The gfx::Image pointer passed to the callback may be NULL if decoding // 3. The gfx::Image pointer passed to the callback will be null if decoding
// failed. // failed.
void LoadIcon(const base::FilePath& file_name, base::CancelableTaskTracker::TaskId LoadIcon(
IconLoader::IconSize size, const base::FilePath& file_name,
const IconRequestCallback& callback); IconLoader::IconSize size,
const IconRequestCallback& callback,
// IconLoader::Delegate interface. base::CancelableTaskTracker* tracker);
bool OnGroupLoaded(IconLoader* loader, const IconGroupID& group) override;
bool OnImageLoaded(IconLoader* loader,
gfx::Image* result,
const IconGroupID& group) override;
private: private:
friend struct base::DefaultSingletonTraits<IconManager>; void OnIconLoaded(IconRequestCallback callback,
base::FilePath file_path,
IconManager(); IconLoader::IconSize size,
~IconManager() override; std::unique_ptr<gfx::Image> result,
const IconLoader::IconGroup& group);
struct CacheKey { struct CacheKey {
CacheKey(const IconGroupID& group, IconLoader::IconSize size); CacheKey(const IconLoader::IconGroup& group, IconLoader::IconSize size);
// Used as a key in the map below, so we need this comparator. // Used as a key in the map below, so we need this comparator.
bool operator<(const CacheKey& other) const; bool operator<(const CacheKey &other) const;
IconGroupID group; IconLoader::IconGroup group;
IconLoader::IconSize size; IconLoader::IconSize size;
}; };
gfx::Image* LookupIconFromGroup(const IconGroupID& group, std::map<base::FilePath, IconLoader::IconGroup> group_cache_;
IconLoader::IconSize size); std::map<CacheKey, std::unique_ptr<gfx::Image>> icon_cache_;
typedef std::map<CacheKey, gfx::Image*> IconMap; base::WeakPtrFactory<IconManager> weak_factory_;
IconMap icon_cache_;
typedef std::map<base::FilePath, IconGroupID> GroupMap;
GroupMap group_cache_;
// Asynchronous requests that have not yet been completed.
struct ClientRequest;
typedef std::map<IconLoader*, ClientRequest> ClientRequests;
ClientRequests requests_;
DISALLOW_COPY_AND_ASSIGN(IconManager); DISALLOW_COPY_AND_ASSIGN(IconManager);
}; };