Add icon fetching sources
This commit is contained in:
parent
1d24a3a175
commit
8e4ed664d9
8 changed files with 668 additions and 1 deletions
|
@ -8,15 +8,16 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "atom/common/asar/asar_util.h"
|
#include "atom/common/asar/asar_util.h"
|
||||||
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||||
#include "atom/common/native_mate_converters/value_converter.h"
|
#include "atom/common/native_mate_converters/value_converter.h"
|
||||||
#include "atom/common/native_mate_converters/callback.h"
|
|
||||||
#include "base/base64.h"
|
#include "base/base64.h"
|
||||||
#include "base/files/file_util.h"
|
#include "base/files/file_util.h"
|
||||||
#include "base/strings/pattern.h"
|
#include "base/strings/pattern.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
|
#include "chrome/browser/ui/webui/fileicon_source.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
#include "native_mate/object_template_builder.h"
|
#include "native_mate/object_template_builder.h"
|
||||||
#include "net/base/data_url.h"
|
#include "net/base/data_url.h"
|
||||||
|
|
49
chromium_src/chrome/browser/icon_loader.cc
Normal file
49
chromium_src/chrome/browser/icon_loader.cc
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// 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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconLoader::ReadGroup() {
|
||||||
|
group_ = ReadGroupIDFromFilepath(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.
|
||||||
|
}
|
105
chromium_src/chrome/browser/icon_loader.h
Normal file
105
chromium_src/chrome/browser/icon_loader.h
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef CHROME_BROWSER_ICON_LOADER_H_
|
||||||
|
#define CHROME_BROWSER_ICON_LOADER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#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> {
|
||||||
|
public:
|
||||||
|
enum IconSize {
|
||||||
|
SMALL = 0, // 16x16
|
||||||
|
NORMAL, // 32x32
|
||||||
|
LARGE, // Windows: 32x32, Linux: 48x48, Mac: Unsupported
|
||||||
|
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;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~Delegate() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
IconLoader(const base::FilePath& file_path,
|
||||||
|
IconSize size,
|
||||||
|
Delegate* delegate);
|
||||||
|
|
||||||
|
// Start reading the icon on the file thread.
|
||||||
|
void Start();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class base::RefCountedThreadSafe<IconLoader>;
|
||||||
|
|
||||||
|
virtual ~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);
|
||||||
|
|
||||||
|
// The thread ReadIcon() should be called on.
|
||||||
|
static content::BrowserThread::ID ReadIconThreadID();
|
||||||
|
|
||||||
|
void ReadGroup();
|
||||||
|
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_;
|
||||||
|
|
||||||
|
IconSize icon_size_;
|
||||||
|
|
||||||
|
std::unique_ptr<gfx::Image> image_;
|
||||||
|
|
||||||
|
Delegate* delegate_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(IconLoader);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHROME_BROWSER_ICON_LOADER_H_
|
148
chromium_src/chrome/browser/icon_manager.cc
Normal file
148
chromium_src/chrome/browser/icon_manager.cc
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "chrome/browser/icon_manager.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#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"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void RunCallbackIfNotCanceled(
|
||||||
|
const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
|
||||||
|
const IconManager::IconRequestCallback& callback,
|
||||||
|
gfx::Image* image) {
|
||||||
|
if (is_canceled.Run())
|
||||||
|
return;
|
||||||
|
callback.Run(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
struct IconManager::ClientRequest {
|
||||||
|
IconRequestCallback callback;
|
||||||
|
base::FilePath file_path;
|
||||||
|
IconLoader::IconSize size;
|
||||||
|
};
|
||||||
|
|
||||||
|
IconManager::IconManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
IconManager::~IconManager() {
|
||||||
|
base::STLDeleteValues(&icon_cache_);
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Image* IconManager::LookupIconFromFilepath(const base::FilePath& file_name,
|
||||||
|
IconLoader::IconSize size) {
|
||||||
|
GroupMap::iterator it = group_cache_.find(file_name);
|
||||||
|
if (it != group_cache_.end())
|
||||||
|
return LookupIconFromGroup(it->second, size);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::CancelableTaskTracker::TaskId IconManager::LoadIcon(
|
||||||
|
const base::FilePath& file_name,
|
||||||
|
IconLoader::IconSize size,
|
||||||
|
const IconRequestCallback& callback,
|
||||||
|
base::CancelableTaskTracker* tracker) {
|
||||||
|
IconLoader* loader = new IconLoader(file_name, size, this);
|
||||||
|
loader->AddRef();
|
||||||
|
loader->Start();
|
||||||
|
|
||||||
|
base::CancelableTaskTracker::IsCanceledCallback is_canceled;
|
||||||
|
base::CancelableTaskTracker::TaskId id =
|
||||||
|
tracker->NewTrackedTaskId(&is_canceled);
|
||||||
|
IconRequestCallback callback_runner = base::Bind(
|
||||||
|
&RunCallbackIfNotCanceled, is_canceled, callback);
|
||||||
|
|
||||||
|
ClientRequest client_request = { callback_runner, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Image* result = LookupIconFromGroup(group, rit->second.size);
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OnImageLoaded(loader, result, 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,
|
||||||
|
IconLoader::IconSize size)
|
||||||
|
: group(group),
|
||||||
|
size(size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IconManager::CacheKey::operator<(const CacheKey &other) const {
|
||||||
|
return std::tie(group, size) < std::tie(other.group, other.size);
|
||||||
|
}
|
121
chromium_src/chrome/browser/icon_manager.h
Normal file
121
chromium_src/chrome/browser/icon_manager.h
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
//
|
||||||
|
// Class for finding and caching Windows explorer icons. The IconManager
|
||||||
|
// lives on the UI thread but performs icon extraction work on the file thread
|
||||||
|
// to avoid blocking the UI thread with potentially expensive COM and disk
|
||||||
|
// operations.
|
||||||
|
//
|
||||||
|
// Terminology
|
||||||
|
//
|
||||||
|
// Windows files have icons associated with them that can be of two types:
|
||||||
|
// 1. "Per class": the icon used for this file is used for all files with the
|
||||||
|
// same file extension or class. Examples are PDF or MP3 files, which use
|
||||||
|
// the same icon for all files of that type.
|
||||||
|
// 2. "Per instance": the icon used for this file is embedded in the file
|
||||||
|
// itself and is unique. Executable files are typically "per instance".
|
||||||
|
//
|
||||||
|
// Files that end in the following extensions are considered "per instance":
|
||||||
|
// .exe
|
||||||
|
// .dll
|
||||||
|
// .ico
|
||||||
|
// The IconManager will do explicit icon loads on the full path of these files
|
||||||
|
// and cache the results per file. All other file types will be looked up by
|
||||||
|
// file extension and the results will be cached per extension. That way, all
|
||||||
|
// .mp3 files will share one icon, but all .exe files will have their own icon.
|
||||||
|
//
|
||||||
|
// POSIX files don't have associated icons. We query the OS by the file's
|
||||||
|
// mime type.
|
||||||
|
//
|
||||||
|
// The IconManager can be queried in two ways:
|
||||||
|
// 1. A quick, synchronous check of its caches which does not touch the disk:
|
||||||
|
// IconManager::LookupIcon()
|
||||||
|
// 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
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Icon bitmaps returned should be treated as const since they may be referenced
|
||||||
|
// by other clients. Make a copy of the icon if you need to modify it.
|
||||||
|
|
||||||
|
#ifndef CHROME_BROWSER_ICON_MANAGER_H_
|
||||||
|
#define CHROME_BROWSER_ICON_MANAGER_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "base/macros.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 {
|
||||||
|
public:
|
||||||
|
IconManager();
|
||||||
|
~IconManager() override;
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
IconLoader::IconSize size);
|
||||||
|
|
||||||
|
typedef base::Callback<void(gfx::Image*)> IconRequestCallback;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// this function is called.
|
||||||
|
//
|
||||||
|
// Note:
|
||||||
|
// 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
|
||||||
|
// failed.
|
||||||
|
base::CancelableTaskTracker::TaskId LoadIcon(
|
||||||
|
const base::FilePath& file_name,
|
||||||
|
IconLoader::IconSize size,
|
||||||
|
const IconRequestCallback& callback,
|
||||||
|
base::CancelableTaskTracker* tracker);
|
||||||
|
|
||||||
|
// IconLoader::Delegate interface.
|
||||||
|
bool OnGroupLoaded(IconLoader* loader, const IconGroupID& group) override;
|
||||||
|
bool OnImageLoaded(IconLoader* loader,
|
||||||
|
gfx::Image* result,
|
||||||
|
const IconGroupID& group) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct CacheKey {
|
||||||
|
CacheKey(const IconGroupID& group, IconLoader::IconSize size);
|
||||||
|
|
||||||
|
// Used as a key in the map below, so we need this comparator.
|
||||||
|
bool operator<(const CacheKey &other) const;
|
||||||
|
|
||||||
|
IconGroupID group;
|
||||||
|
IconLoader::IconSize size;
|
||||||
|
};
|
||||||
|
|
||||||
|
gfx::Image* LookupIconFromGroup(const IconGroupID& group,
|
||||||
|
IconLoader::IconSize size);
|
||||||
|
|
||||||
|
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_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(IconManager);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHROME_BROWSER_ICON_MANAGER_H_
|
164
chromium_src/chrome/browser/ui/webui/fileicon_source.cc
Normal file
164
chromium_src/chrome/browser/ui/webui/fileicon_source.cc
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "chrome/browser/ui/webui/fileicon_source.h"
|
||||||
|
|
||||||
|
#include "base/bind.h"
|
||||||
|
#include "base/callback.h"
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "base/memory/ref_counted_memory.h"
|
||||||
|
#include "base/message_loop/message_loop.h"
|
||||||
|
#include "base/strings/string_split.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "chrome/browser/browser_process.h"
|
||||||
|
#include "net/base/escape.h"
|
||||||
|
#include "third_party/skia/include/core/SkBitmap.h"
|
||||||
|
#include "ui/base/webui/web_ui_util.h"
|
||||||
|
#include "ui/gfx/codec/png_codec.h"
|
||||||
|
#include "ui/gfx/image/image.h"
|
||||||
|
#include "ui/gfx/image/image_skia.h"
|
||||||
|
#include "url/gurl.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
typedef std::map<std::string, IconLoader::IconSize> QueryIconSizeMap;
|
||||||
|
|
||||||
|
// The path used in internal URLs to file icon data.
|
||||||
|
const char kFileIconPath[] = "fileicon";
|
||||||
|
|
||||||
|
// URL parameter specifying icon size.
|
||||||
|
const char kIconSize[] = "iconsize";
|
||||||
|
|
||||||
|
// URL parameter specifying scale factor.
|
||||||
|
const char kScaleFactor[] = "scale";
|
||||||
|
|
||||||
|
// Assuming the url is of the form '/path?query', convert the path portion into
|
||||||
|
// a FilePath and return the resulting |file_path| and |query|. The path
|
||||||
|
// portion may have been encoded using encodeURIComponent().
|
||||||
|
void GetFilePathAndQuery(const std::string& url,
|
||||||
|
base::FilePath* file_path,
|
||||||
|
std::string* query) {
|
||||||
|
// We receive the url with chrome://fileicon/ stripped but GURL expects it.
|
||||||
|
const GURL gurl("chrome://fileicon/" + url);
|
||||||
|
std::string path = net::UnescapeURLComponent(
|
||||||
|
gurl.path().substr(1),
|
||||||
|
net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
|
||||||
|
net::UnescapeRule::PATH_SEPARATORS | net::UnescapeRule::SPACES);
|
||||||
|
|
||||||
|
*file_path = base::FilePath::FromUTF8Unsafe(path);
|
||||||
|
*file_path = file_path->NormalizePathSeparators();
|
||||||
|
query->assign(gurl.query());
|
||||||
|
}
|
||||||
|
|
||||||
|
IconLoader::IconSize SizeStringToIconSize(const std::string& size_string) {
|
||||||
|
if (size_string == "small") return IconLoader::SMALL;
|
||||||
|
if (size_string == "large") return IconLoader::LARGE;
|
||||||
|
// We default to NORMAL if we don't recognize the size_string. Including
|
||||||
|
// size_string=="normal".
|
||||||
|
return IconLoader::NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple parser for data on the query.
|
||||||
|
void ParseQueryParams(const std::string& query,
|
||||||
|
float* scale_factor,
|
||||||
|
IconLoader::IconSize* icon_size) {
|
||||||
|
base::StringPairs parameters;
|
||||||
|
if (icon_size)
|
||||||
|
*icon_size = IconLoader::NORMAL;
|
||||||
|
if (scale_factor)
|
||||||
|
*scale_factor = 1.0f;
|
||||||
|
base::SplitStringIntoKeyValuePairs(query, '=', '&', ¶meters);
|
||||||
|
for (base::StringPairs::const_iterator iter = parameters.begin();
|
||||||
|
iter != parameters.end(); ++iter) {
|
||||||
|
if (icon_size && iter->first == kIconSize)
|
||||||
|
*icon_size = SizeStringToIconSize(iter->second);
|
||||||
|
else if (scale_factor && iter->first == kScaleFactor)
|
||||||
|
webui::ParseScaleFactor(iter->second, scale_factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
FileIconSource::IconRequestDetails::IconRequestDetails() : scale_factor(1.0f) {
|
||||||
|
}
|
||||||
|
|
||||||
|
FileIconSource::IconRequestDetails::IconRequestDetails(
|
||||||
|
const IconRequestDetails& other) = default;
|
||||||
|
|
||||||
|
FileIconSource::IconRequestDetails::~IconRequestDetails() {
|
||||||
|
}
|
||||||
|
|
||||||
|
FileIconSource::FileIconSource() {}
|
||||||
|
|
||||||
|
FileIconSource::~FileIconSource() {}
|
||||||
|
|
||||||
|
void FileIconSource::FetchFileIcon(
|
||||||
|
const base::FilePath& path,
|
||||||
|
float scale_factor,
|
||||||
|
IconLoader::IconSize icon_size,
|
||||||
|
const content::URLDataSource::GotDataCallback& callback) {
|
||||||
|
IconManager* im = g_browser_process->icon_manager();
|
||||||
|
gfx::Image* icon = im->LookupIconFromFilepath(path, icon_size);
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
|
||||||
|
gfx::PNGCodec::EncodeBGRASkBitmap(
|
||||||
|
icon->ToImageSkia()->GetRepresentation(scale_factor).sk_bitmap(),
|
||||||
|
false,
|
||||||
|
&icon_data->data());
|
||||||
|
|
||||||
|
callback.Run(icon_data.get());
|
||||||
|
} else {
|
||||||
|
// Attach the ChromeURLDataManager request ID to the history request.
|
||||||
|
IconRequestDetails details;
|
||||||
|
details.callback = callback;
|
||||||
|
details.scale_factor = scale_factor;
|
||||||
|
|
||||||
|
// Icon was not in cache, go fetch it slowly.
|
||||||
|
im->LoadIcon(path,
|
||||||
|
icon_size,
|
||||||
|
base::Bind(&FileIconSource::OnFileIconDataAvailable,
|
||||||
|
base::Unretained(this), details),
|
||||||
|
&cancelable_task_tracker_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FileIconSource::GetSource() const {
|
||||||
|
return kFileIconPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void FileIconSource::StartDataRequest(
|
||||||
|
// const std::string& url_path,
|
||||||
|
// const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
|
||||||
|
// const content::URLDataSource::GotDataCallback& callback) {
|
||||||
|
// std::string query;
|
||||||
|
// base::FilePath file_path;
|
||||||
|
// IconLoader::IconSize icon_size;
|
||||||
|
// float scale_factor = 1.0f;
|
||||||
|
// GetFilePathAndQuery(url_path, &file_path, &query);
|
||||||
|
// ParseQueryParams(query, &scale_factor, &icon_size);
|
||||||
|
// FetchFileIcon(file_path, scale_factor, icon_size, callback);
|
||||||
|
// }
|
||||||
|
|
||||||
|
std::string FileIconSource::GetMimeType(const std::string&) const {
|
||||||
|
// Rely on image decoder inferring the correct type.
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileIconSource::OnFileIconDataAvailable(const IconRequestDetails& details,
|
||||||
|
gfx::Image* icon) {
|
||||||
|
if (icon) {
|
||||||
|
scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
|
||||||
|
gfx::PNGCodec::EncodeBGRASkBitmap(
|
||||||
|
icon->ToImageSkia()->GetRepresentation(
|
||||||
|
details.scale_factor).sk_bitmap(),
|
||||||
|
false,
|
||||||
|
&icon_data->data());
|
||||||
|
|
||||||
|
details.callback.Run(icon_data.get());
|
||||||
|
} else {
|
||||||
|
// TODO(glen): send a dummy icon.
|
||||||
|
details.callback.Run(NULL);
|
||||||
|
}
|
||||||
|
}
|
73
chromium_src/chrome/browser/ui/webui/fileicon_source.h
Normal file
73
chromium_src/chrome/browser/ui/webui/fileicon_source.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef CHROME_BROWSER_UI_WEBUI_FILEICON_SOURCE_H_
|
||||||
|
#define CHROME_BROWSER_UI_WEBUI_FILEICON_SOURCE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "base/macros.h"
|
||||||
|
#include "base/task/cancelable_task_tracker.h"
|
||||||
|
#include "chrome/browser/icon_manager.h"
|
||||||
|
#include "content/public/browser/url_data_source.h"
|
||||||
|
|
||||||
|
namespace gfx {
|
||||||
|
class Image;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
class ResourceRequestInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileIconSource is the gateway between network-level chrome:
|
||||||
|
// requests for favicons and the history backend that serves these.
|
||||||
|
class FileIconSource : public content::URLDataSource {
|
||||||
|
public:
|
||||||
|
FileIconSource();
|
||||||
|
|
||||||
|
// content::URLDataSource implementation.
|
||||||
|
std::string GetSource() const override;
|
||||||
|
// void StartDataRequest(
|
||||||
|
// const std::string& path,
|
||||||
|
// const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
|
||||||
|
// const content::URLDataSource::GotDataCallback& callback) override;
|
||||||
|
std::string GetMimeType(const std::string&) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~FileIconSource() override;
|
||||||
|
|
||||||
|
// Once the |path| and |icon_size| has been determined from the request, this
|
||||||
|
// function is called to perform the actual fetch. Declared as virtual for
|
||||||
|
// testing.
|
||||||
|
virtual void FetchFileIcon(
|
||||||
|
const base::FilePath& path,
|
||||||
|
float scale_factor,
|
||||||
|
IconLoader::IconSize icon_size,
|
||||||
|
const content::URLDataSource::GotDataCallback& callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Contains the necessary information for completing an icon fetch request.
|
||||||
|
struct IconRequestDetails {
|
||||||
|
IconRequestDetails();
|
||||||
|
IconRequestDetails(const IconRequestDetails& other);
|
||||||
|
~IconRequestDetails();
|
||||||
|
|
||||||
|
// The callback to run with the response.
|
||||||
|
content::URLDataSource::GotDataCallback callback;
|
||||||
|
|
||||||
|
// The requested scale factor to respond with.
|
||||||
|
float scale_factor;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Called when favicon data is available from the history backend.
|
||||||
|
void OnFileIconDataAvailable(const IconRequestDetails& details,
|
||||||
|
gfx::Image* icon);
|
||||||
|
|
||||||
|
// Tracks tasks requesting file icons.
|
||||||
|
base::CancelableTaskTracker cancelable_task_tracker_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(FileIconSource);
|
||||||
|
};
|
||||||
|
#endif // CHROME_BROWSER_UI_WEBUI_FILEICON_SOURCE_H_
|
|
@ -475,6 +475,10 @@
|
||||||
'chromium_src/chrome/browser/chrome_process_finder_win.cc',
|
'chromium_src/chrome/browser/chrome_process_finder_win.cc',
|
||||||
'chromium_src/chrome/browser/chrome_process_finder_win.h',
|
'chromium_src/chrome/browser/chrome_process_finder_win.h',
|
||||||
'chromium_src/chrome/browser/chrome_notification_types.h',
|
'chromium_src/chrome/browser/chrome_notification_types.h',
|
||||||
|
'chromium_src/chrome/browser/icon_loader.cc',
|
||||||
|
'chromium_src/chrome/browser/icon_loader.h',
|
||||||
|
'chromium_src/chrome/browser/icon_manager.cc',
|
||||||
|
'chromium_src/chrome/browser/icon_manager.h',
|
||||||
'chromium_src/chrome/browser/extensions/global_shortcut_listener.cc',
|
'chromium_src/chrome/browser/extensions/global_shortcut_listener.cc',
|
||||||
'chromium_src/chrome/browser/extensions/global_shortcut_listener.h',
|
'chromium_src/chrome/browser/extensions/global_shortcut_listener.h',
|
||||||
'chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm',
|
'chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm',
|
||||||
|
@ -543,6 +547,8 @@
|
||||||
'chromium_src/chrome/browser/ui/views/color_chooser_aura.h',
|
'chromium_src/chrome/browser/ui/views/color_chooser_aura.h',
|
||||||
'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc',
|
'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc',
|
||||||
'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h',
|
'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h',
|
||||||
|
'chromium_src/chrome/browser/ui/webui/fileicon_source.cc',
|
||||||
|
'chromium_src/chrome/browser/ui/webui/fileicon_source.h',
|
||||||
'chromium_src/chrome/common/chrome_constants.cc',
|
'chromium_src/chrome/common/chrome_constants.cc',
|
||||||
'chromium_src/chrome/common/chrome_constants.h',
|
'chromium_src/chrome/common/chrome_constants.h',
|
||||||
'chromium_src/chrome/common/chrome_paths.cc',
|
'chromium_src/chrome/common/chrome_paths.cc',
|
||||||
|
|
Loading…
Reference in a new issue