1// Copyright (c) 2012 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// Class for finding and caching Windows explorer icons. The IconManager
6// lives on the UI thread but performs icon extraction work on the file thread
7// to avoid blocking the UI thread with potentially expensive COM and disk
8// operations.
9//
10// Terminology
11//
12// Windows files have icons associated with them that can be of two types:
13//   1. "Per class": the icon used for this file is used for all files with the
14//      same file extension or class. Examples are PDF or MP3 files, which use
15//      the same icon for all files of that type.
16//   2. "Per instance": the icon used for this file is embedded in the file
17//      itself and is unique. Executable files are typically "per instance".
18//
19// Files that end in the following extensions are considered "per instance":
20//   .exe
21//   .dll
22//   .ico
23// The IconManager will do explicit icon loads on the full path of these files
24// and cache the results per file. All other file types will be looked up by
25// file extension and the results will be cached per extension. That way, all
26// .mp3 files will share one icon, but all .exe files will have their own icon.
27//
28// POSIX files don't have associated icons. We query the OS by the file's
29// mime type.
30//
31// The IconManager can be queried in two ways:
32//   1. A quick, synchronous check of its caches which does not touch the disk:
33//      IconManager::LookupIcon()
34//   2. An asynchronous icon load from a file on the file thread:
35//      IconManager::LoadIcon()
36//
37// When using the second (asychronous) method, callers must supply a callback
38// which will be run once the icon has been extracted. The icon manager will
39// cache the results of the icon extraction so that subsequent lookups will be
40// fast.
41//
42// Icon bitmaps returned should be treated as const since they may be referenced
43// by other clients. Make a copy of the icon if you need to modify it.
44
45#ifndef CHROME_BROWSER_ICON_MANAGER_H_
46#define CHROME_BROWSER_ICON_MANAGER_H_
47
48#include <map>
49
50#include "base/files/file_path.h"
51#include "base/task/cancelable_task_tracker.h"
52#include "chrome/browser/icon_loader.h"
53#include "ui/gfx/image/image.h"
54
55class IconManager : public IconLoader::Delegate {
56 public:
57  IconManager();
58  virtual ~IconManager();
59
60  // Synchronous call to examine the internal caches for the icon. Returns the
61  // icon if we have already loaded it, NULL if we don't have it and must load
62  // it via 'LoadIcon'. The returned bitmap is owned by the IconManager and must
63  // not be free'd by the caller. If the caller needs to modify the icon, it
64  // must make a copy and modify the copy.
65  gfx::Image* LookupIconFromFilepath(const base::FilePath& file_name,
66                                     IconLoader::IconSize size);
67
68  typedef base::Callback<void(gfx::Image*)> IconRequestCallback;
69
70  // Asynchronous call to lookup and return the icon associated with file. The
71  // work is done on the file thread, with the callbacks running on the thread
72  // this function is called.
73  //
74  // Note:
75  // 1. This does *not* check the cache.
76  // 2. The returned bitmap pointer is *not* owned by callback. So callback
77  //    should never keep it or delete it.
78  // 3. The gfx::Image pointer passed to the callback may be NULL if decoding
79  //    failed.
80  base::CancelableTaskTracker::TaskId LoadIcon(
81      const base::FilePath& file_name,
82      IconLoader::IconSize size,
83      const IconRequestCallback& callback,
84      base::CancelableTaskTracker* tracker);
85
86  // IconLoader::Delegate interface.
87  virtual bool OnGroupLoaded(IconLoader* loader,
88                             const IconGroupID& group) OVERRIDE;
89  virtual bool OnImageLoaded(IconLoader* loader,
90                             gfx::Image* result,
91                             const IconGroupID& group) OVERRIDE;
92
93 private:
94  struct CacheKey {
95    CacheKey(const IconGroupID& group, IconLoader::IconSize size);
96
97    // Used as a key in the map below, so we need this comparator.
98    bool operator<(const CacheKey &other) const;
99
100    IconGroupID group;
101    IconLoader::IconSize size;
102  };
103
104  gfx::Image* LookupIconFromGroup(const IconGroupID& group,
105                                  IconLoader::IconSize size);
106
107  typedef std::map<CacheKey, gfx::Image*> IconMap;
108  IconMap icon_cache_;
109
110  typedef std::map<base::FilePath, IconGroupID> GroupMap;
111  GroupMap group_cache_;
112
113  // Asynchronous requests that have not yet been completed.
114  struct ClientRequest;
115  typedef std::map<IconLoader*, ClientRequest> ClientRequests;
116  ClientRequests requests_;
117
118  DISALLOW_COPY_AND_ASSIGN(IconManager);
119};
120
121#endif  // CHROME_BROWSER_ICON_MANAGER_H_
122