Merge pull request #8704 from YurySolovyov/update-icon-fetch-impl
Update icon loading API implementation
This commit is contained in:
commit
91677ade89
11 changed files with 191 additions and 246 deletions
|
@ -30,6 +30,7 @@
|
|||
#include "base/path_service.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "brightray/browser/brightray_paths.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/icon_manager.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "content/public/browser/browser_accessibility_state.h"
|
||||
|
@ -890,15 +891,16 @@ void App::GetFileIcon(const base::FilePath& path,
|
|||
return;
|
||||
}
|
||||
|
||||
IconManager* icon_manager = IconManager::GetInstance();
|
||||
gfx::Image* icon = icon_manager->LookupIconFromFilepath(normalized_path,
|
||||
icon_size);
|
||||
auto icon_manager = g_browser_process->GetIconManager();
|
||||
gfx::Image* icon =
|
||||
icon_manager->LookupIconFromFilepath(normalized_path, icon_size);
|
||||
if (icon) {
|
||||
callback.Run(v8::Null(isolate()), *icon);
|
||||
} else {
|
||||
icon_manager->LoadIcon(normalized_path, icon_size,
|
||||
base::Bind(&OnIconDataAvailable, isolate(),
|
||||
callback));
|
||||
icon_manager->LoadIcon(
|
||||
normalized_path, icon_size,
|
||||
base::Bind(&OnIconDataAvailable, isolate(), callback),
|
||||
&cancelable_task_tracker_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/browser_observer.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 "content/public/browser/gpu_data_manager_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
@ -150,6 +151,9 @@ class App : public AtomBrowserClient::Delegate,
|
|||
std::unique_ptr<CertificateManagerModel> certificate_manager_model_;
|
||||
#endif
|
||||
|
||||
// Tracks tasks requesting file icons.
|
||||
base::CancelableTaskTracker cancelable_task_tracker_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(App);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
|
||||
#include "chrome/browser/browser_process.h"
|
||||
|
||||
#include "chrome/browser/icon_manager.h"
|
||||
#include "chrome/browser/printing/print_job_manager.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
BrowserProcess* g_browser_process = NULL;
|
||||
|
||||
BrowserProcess::BrowserProcess()
|
||||
: print_job_manager_(new printing::PrintJobManager) {
|
||||
: print_job_manager_(new printing::PrintJobManager),
|
||||
icon_manager_(new IconManager) {
|
||||
g_browser_process = this;
|
||||
}
|
||||
|
||||
|
@ -22,6 +24,12 @@ std::string BrowserProcess::GetApplicationLocale() {
|
|||
return l10n_util::GetApplicationLocale("");
|
||||
}
|
||||
|
||||
IconManager* BrowserProcess::GetIconManager() {
|
||||
if (!icon_manager_.get())
|
||||
icon_manager_.reset(new IconManager);
|
||||
return icon_manager_.get();
|
||||
}
|
||||
|
||||
printing::PrintJobManager* BrowserProcess::print_job_manager() {
|
||||
return print_job_manager_.get();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include "base/macros.h"
|
||||
|
||||
class IconManager;
|
||||
|
||||
namespace printing {
|
||||
class PrintJobManager;
|
||||
}
|
||||
|
@ -27,11 +29,13 @@ class BrowserProcess {
|
|||
~BrowserProcess();
|
||||
|
||||
std::string GetApplicationLocale();
|
||||
IconManager* GetIconManager();
|
||||
|
||||
printing::PrintJobManager* print_job_manager();
|
||||
|
||||
private:
|
||||
std::unique_ptr<printing::PrintJobManager> print_job_manager_;
|
||||
std::unique_ptr<IconManager> icon_manager_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserProcess);
|
||||
};
|
||||
|
|
|
@ -3,46 +3,40 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/browser/icon_loader.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
IconLoader::IconLoader(const base::FilePath& file_path,
|
||||
IconSize size,
|
||||
Delegate* delegate)
|
||||
: target_task_runner_(NULL),
|
||||
file_path_(file_path),
|
||||
icon_size_(size),
|
||||
delegate_(delegate) {}
|
||||
|
||||
IconLoader::~IconLoader() {}
|
||||
// static
|
||||
IconLoader* IconLoader::Create(const base::FilePath& file_path,
|
||||
IconSize size,
|
||||
IconLoadedCallback callback) {
|
||||
return new IconLoader(file_path, size, callback);
|
||||
}
|
||||
|
||||
void IconLoader::Start() {
|
||||
target_task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
||||
|
||||
BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
|
||||
base::Bind(&IconLoader::ReadGroup, this),
|
||||
base::Bind(&IconLoader::OnReadGroup, this));
|
||||
BrowserThread::PostTaskAndReply(
|
||||
BrowserThread::FILE, FROM_HERE,
|
||||
base::Bind(&IconLoader::ReadGroup, base::Unretained(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() {
|
||||
group_ = ReadGroupIDFromFilepath(file_path_);
|
||||
group_ = GroupForFilepath(file_path_);
|
||||
}
|
||||
|
||||
void IconLoader::OnReadGroup() {
|
||||
if (IsIconMutableFromFilepath(file_path_) ||
|
||||
!delegate_->OnGroupLoaded(this, group_)) {
|
||||
BrowserThread::PostTask(ReadIconThreadID(), FROM_HERE,
|
||||
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.
|
||||
BrowserThread::PostTask(
|
||||
ReadIconThreadID(), FROM_HERE,
|
||||
base::Bind(&IconLoader::ReadIcon, base::Unretained(this)));
|
||||
}
|
||||
|
|
|
@ -8,31 +8,30 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "build/build_config.h"
|
||||
#include "content/public/browser/browser_thread.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
|
||||
// thread. Returns the icon in the form of an ImageSkia.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class IconLoader : public base::RefCountedThreadSafe<IconLoader> {
|
||||
class IconLoader {
|
||||
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 {
|
||||
SMALL = 0, // 16x16
|
||||
NORMAL, // 32x32
|
||||
|
@ -40,42 +39,32 @@ class IconLoader : public base::RefCountedThreadSafe<IconLoader> {
|
|||
ALL, // All sizes available
|
||||
};
|
||||
|
||||
class Delegate {
|
||||
public:
|
||||
// Invoked when an icon group has been read, but before the icon data
|
||||
// is read. If the icon is already cached, this method should call and
|
||||
// return the results of OnImageLoaded with the cached image.
|
||||
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;
|
||||
// The callback invoked when an icon has been read. The parameters are:
|
||||
// - The icon that was loaded, or null if there was a failure to load it.
|
||||
// - The determined group from the original requested path.
|
||||
using IconLoadedCallback =
|
||||
base::Callback<void(std::unique_ptr<gfx::Image>, const IconGroup&)>;
|
||||
|
||||
protected:
|
||||
virtual ~Delegate() {}
|
||||
};
|
||||
// Creates an IconLoader, which owns itself. If the IconLoader might outlive
|
||||
// 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,
|
||||
IconSize size,
|
||||
Delegate* delegate);
|
||||
|
||||
// Start reading the icon on the file thread.
|
||||
// Starts the process of reading the icon. When the reading of the icon is
|
||||
// complete, the IconLoadedCallback callback will be fulfilled, and the
|
||||
// IconLoader will delete itself.
|
||||
void Start();
|
||||
|
||||
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
|
||||
// is in icon_loader_[platform].cc.
|
||||
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);
|
||||
// Given a file path, get the group for the given file.
|
||||
static IconGroup GroupForFilepath(const base::FilePath& file_path);
|
||||
|
||||
// The thread ReadIcon() should be called on.
|
||||
static content::BrowserThread::ID ReadIconThreadID();
|
||||
|
@ -84,20 +73,18 @@ class IconLoader : public base::RefCountedThreadSafe<IconLoader> {
|
|||
void OnReadGroup();
|
||||
void ReadIcon();
|
||||
|
||||
void NotifyDelegate();
|
||||
|
||||
// The task runner object of the thread in which we notify the delegate.
|
||||
scoped_refptr<base::SingleThreadTaskRunner> target_task_runner_;
|
||||
|
||||
base::FilePath file_path_;
|
||||
|
||||
IconGroupID group_;
|
||||
IconGroup group_;
|
||||
|
||||
IconSize icon_size_;
|
||||
|
||||
std::unique_ptr<gfx::Image> image_;
|
||||
|
||||
Delegate* delegate_;
|
||||
IconLoadedCallback callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(IconLoader);
|
||||
};
|
||||
|
|
|
@ -10,14 +10,9 @@
|
|||
#include "ui/views/linux_ui/linux_ui.h"
|
||||
|
||||
// static
|
||||
IconGroupID IconLoader::ReadGroupIDFromFilepath(
|
||||
const base::FilePath& filepath) {
|
||||
return base::nix::GetFileMimeType(filepath);
|
||||
}
|
||||
|
||||
// static
|
||||
bool IconLoader::IsIconMutableFromFilepath(const base::FilePath&) {
|
||||
return false;
|
||||
IconLoader::IconGroup IconLoader::GroupForFilepath(
|
||||
const base::FilePath& file_path) {
|
||||
return base::nix::GetFileMimeType(file_path);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -50,6 +45,7 @@ void IconLoader::ReadIcon() {
|
|||
image_.reset(new gfx::Image(image));
|
||||
}
|
||||
|
||||
target_task_runner_->PostTask(FROM_HERE,
|
||||
base::Bind(&IconLoader::NotifyDelegate, this));
|
||||
target_task_runner_->PostTask(
|
||||
FROM_HERE, base::Bind(callback_, base::Passed(&image_), group_));
|
||||
delete this;
|
||||
}
|
||||
|
|
|
@ -15,14 +15,9 @@
|
|||
#include "ui/gfx/image/image_skia_util_mac.h"
|
||||
|
||||
// static
|
||||
IconGroupID IconLoader::ReadGroupIDFromFilepath(
|
||||
const base::FilePath& filepath) {
|
||||
return filepath.Extension();
|
||||
}
|
||||
|
||||
// static
|
||||
bool IconLoader::IsIconMutableFromFilepath(const base::FilePath&) {
|
||||
return false;
|
||||
IconLoader::IconGroup IconLoader::GroupForFilepath(
|
||||
const base::FilePath& file_path) {
|
||||
return file_path.Extension();
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -57,6 +52,7 @@ void IconLoader::ReadIcon() {
|
|||
}
|
||||
}
|
||||
|
||||
target_task_runner_->PostTask(FROM_HERE,
|
||||
base::Bind(&IconLoader::NotifyDelegate, this));
|
||||
target_task_runner_->PostTask(
|
||||
FROM_HERE, base::Bind(callback_, base::Passed(&image_), group_));
|
||||
delete this;
|
||||
}
|
||||
|
|
|
@ -17,18 +17,15 @@
|
|||
#include "ui/gfx/image/image_skia.h"
|
||||
|
||||
// static
|
||||
IconGroupID IconLoader::ReadGroupIDFromFilepath(
|
||||
const base::FilePath& filepath) {
|
||||
if (!IsIconMutableFromFilepath(filepath))
|
||||
return filepath.Extension();
|
||||
return filepath.value();
|
||||
}
|
||||
IconLoader::IconGroup IconLoader::GroupForFilepath(
|
||||
const base::FilePath& file_path) {
|
||||
if (file_path.MatchesExtension(L".exe") ||
|
||||
file_path.MatchesExtension(L".dll") ||
|
||||
file_path.MatchesExtension(L".ico")) {
|
||||
return file_path.value();
|
||||
}
|
||||
|
||||
// static
|
||||
bool IconLoader::IsIconMutableFromFilepath(const base::FilePath& filepath) {
|
||||
return filepath.MatchesExtension(L".exe") ||
|
||||
filepath.MatchesExtension(L".dll") ||
|
||||
filepath.MatchesExtension(L".ico");
|
||||
return file_path.Extension();
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -54,22 +51,22 @@ void IconLoader::ReadIcon() {
|
|||
|
||||
image_.reset();
|
||||
|
||||
SHFILEINFO file_info = {0};
|
||||
SHFILEINFO file_info = { 0 };
|
||||
if (SHGetFileInfo(group_.c_str(), FILE_ATTRIBUTE_NORMAL, &file_info,
|
||||
sizeof(SHFILEINFO),
|
||||
SHGFI_ICON | size | SHGFI_USEFILEATTRIBUTES)) {
|
||||
sizeof(SHFILEINFO),
|
||||
SHGFI_ICON | size | SHGFI_USEFILEATTRIBUTES)) {
|
||||
std::unique_ptr<SkBitmap> bitmap(
|
||||
IconUtil::CreateSkBitmapFromHICON(file_info.hIcon));
|
||||
if (bitmap.get()) {
|
||||
gfx::ImageSkia image_skia(
|
||||
gfx::ImageSkiaRep(*bitmap, display::win::GetDPIScale()));
|
||||
gfx::ImageSkia image_skia(gfx::ImageSkiaRep(*bitmap,
|
||||
display::win::GetDPIScale()));
|
||||
image_skia.MakeThreadSafe();
|
||||
image_.reset(new gfx::Image(image_skia));
|
||||
DestroyIcon(file_info.hIcon);
|
||||
}
|
||||
}
|
||||
|
||||
// Always notify the delegate, regardless of success.
|
||||
target_task_runner_->PostTask(FROM_HERE,
|
||||
base::Bind(&IconLoader::NotifyDelegate, this));
|
||||
target_task_runner_->PostTask(
|
||||
FROM_HERE, base::Bind(callback_, base::Passed(&image_), group_));
|
||||
delete this;
|
||||
}
|
||||
|
|
|
@ -8,121 +8,86 @@
|
|||
#include <tuple>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "base/task_runner.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
struct IconManager::ClientRequest {
|
||||
IconRequestCallback callback;
|
||||
base::FilePath file_path;
|
||||
IconLoader::IconSize size;
|
||||
};
|
||||
namespace {
|
||||
|
||||
// static
|
||||
IconManager* IconManager::GetInstance() {
|
||||
return base::Singleton<IconManager>::get();
|
||||
void RunCallbackIfNotCanceled(
|
||||
const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
|
||||
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() {
|
||||
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) {
|
||||
GroupMap::iterator it = group_cache_.find(file_name);
|
||||
if (it != group_cache_.end())
|
||||
return LookupIconFromGroup(it->second, size);
|
||||
auto group_it = group_cache_.find(file_path);
|
||||
if (group_it == group_cache_.end())
|
||||
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,
|
||||
IconLoader::IconSize size) {
|
||||
IconMap::iterator it = icon_cache_.find(CacheKey(group, size));
|
||||
if (it != icon_cache_.end())
|
||||
return it->second;
|
||||
base::CancelableTaskTracker::TaskId IconManager::LoadIcon(
|
||||
const base::FilePath& file_path,
|
||||
IconLoader::IconSize size,
|
||||
const IconRequestCallback& callback,
|
||||
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;
|
||||
}
|
||||
|
||||
void IconManager::LoadIcon(const base::FilePath& file_name,
|
||||
IconLoader::IconSize size,
|
||||
const IconRequestCallback& callback) {
|
||||
IconLoader* loader = new IconLoader(file_name, size, this);
|
||||
loader->AddRef();
|
||||
IconLoader* loader = IconLoader::Create(
|
||||
file_path, size,
|
||||
base::Bind(&IconManager::OnIconLoaded, weak_factory_.GetWeakPtr(),
|
||||
callback_runner, file_path, size));
|
||||
loader->Start();
|
||||
|
||||
ClientRequest client_request = {callback, file_name, size};
|
||||
requests_[loader] = client_request;
|
||||
return id;
|
||||
}
|
||||
|
||||
// IconLoader::Delegate implementation -----------------------------------------
|
||||
|
||||
bool IconManager::OnGroupLoaded(IconLoader* loader, const IconGroupID& group) {
|
||||
ClientRequests::iterator rit = requests_.find(loader);
|
||||
if (rit == requests_.end()) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
void IconManager::OnIconLoaded(IconRequestCallback callback,
|
||||
base::FilePath file_path,
|
||||
IconLoader::IconSize size,
|
||||
std::unique_ptr<gfx::Image> result,
|
||||
const IconLoader::IconGroup& group) {
|
||||
// Cache the bitmap. Watch out: |result| may be null, which indicates a
|
||||
// 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);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return OnImageLoaded(loader, result, group);
|
||||
group_cache_[file_path] = group;
|
||||
}
|
||||
|
||||
bool IconManager::OnImageLoaded(IconLoader* loader,
|
||||
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,
|
||||
IconManager::CacheKey::CacheKey(const IconLoader::IconGroup& group,
|
||||
IconLoader::IconSize 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);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
// 2. An asynchronous icon load from a file on the file thread:
|
||||
// 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
|
||||
// cache the results of the icon extraction so that subsequent lookups will be
|
||||
// fast.
|
||||
|
@ -46,25 +46,29 @@
|
|||
#define CHROME_BROWSER_ICON_MANAGER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "base/files/file_path.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 "ui/gfx/image/image.h"
|
||||
|
||||
class IconManager : public IconLoader::Delegate {
|
||||
class IconManager {
|
||||
public:
|
||||
static IconManager* GetInstance();
|
||||
IconManager();
|
||||
~IconManager();
|
||||
|
||||
// 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
|
||||
// it via 'LoadIcon'. The returned bitmap is owned by the IconManager and must
|
||||
// not be free'd by the caller. If the caller needs to modify the icon, it
|
||||
// must make a copy and modify the copy.
|
||||
gfx::Image* LookupIconFromFilepath(const base::FilePath& file_name,
|
||||
// icon if we have already loaded it, or null if we don't have it and must
|
||||
// load it via LoadIcon(). The returned bitmap is owned by the IconManager and
|
||||
// must not be free'd by the caller. If the caller needs to modify the icon,
|
||||
// it must make a copy and modify the copy.
|
||||
gfx::Image* LookupIconFromFilepath(const base::FilePath& file_path,
|
||||
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
|
||||
// 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.
|
||||
// 2. The returned bitmap pointer is *not* owned by callback. So callback
|
||||
// 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.
|
||||
void LoadIcon(const base::FilePath& file_name,
|
||||
IconLoader::IconSize size,
|
||||
const IconRequestCallback& callback);
|
||||
|
||||
// IconLoader::Delegate interface.
|
||||
bool OnGroupLoaded(IconLoader* loader, const IconGroupID& group) override;
|
||||
bool OnImageLoaded(IconLoader* loader,
|
||||
gfx::Image* result,
|
||||
const IconGroupID& group) override;
|
||||
base::CancelableTaskTracker::TaskId LoadIcon(
|
||||
const base::FilePath& file_name,
|
||||
IconLoader::IconSize size,
|
||||
const IconRequestCallback& callback,
|
||||
base::CancelableTaskTracker* tracker);
|
||||
|
||||
private:
|
||||
friend struct base::DefaultSingletonTraits<IconManager>;
|
||||
|
||||
IconManager();
|
||||
~IconManager() override;
|
||||
void OnIconLoaded(IconRequestCallback callback,
|
||||
base::FilePath file_path,
|
||||
IconLoader::IconSize size,
|
||||
std::unique_ptr<gfx::Image> result,
|
||||
const IconLoader::IconGroup& group);
|
||||
|
||||
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.
|
||||
bool operator<(const CacheKey& other) const;
|
||||
bool operator<(const CacheKey &other) const;
|
||||
|
||||
IconGroupID group;
|
||||
IconLoader::IconGroup group;
|
||||
IconLoader::IconSize size;
|
||||
};
|
||||
|
||||
gfx::Image* LookupIconFromGroup(const IconGroupID& group,
|
||||
IconLoader::IconSize size);
|
||||
std::map<base::FilePath, IconLoader::IconGroup> group_cache_;
|
||||
std::map<CacheKey, std::unique_ptr<gfx::Image>> icon_cache_;
|
||||
|
||||
typedef std::map<CacheKey, gfx::Image*> IconMap;
|
||||
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_;
|
||||
base::WeakPtrFactory<IconManager> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(IconManager);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue