Add icon fetching sources
authorYury Solovyov <biohazard707@gmail.com>
Sat, 29 Oct 2016 12:35:50 +0000 (15:35 +0300)
committerKevin Sawicki <kevinsawicki@gmail.com>
Tue, 7 Feb 2017 17:48:12 +0000 (09:48 -0800)
atom/common/api/atom_api_native_image.cc
chromium_src/chrome/browser/icon_loader.cc [new file with mode: 0644]
chromium_src/chrome/browser/icon_loader.h [new file with mode: 0644]
chromium_src/chrome/browser/icon_manager.cc [new file with mode: 0644]
chromium_src/chrome/browser/icon_manager.h [new file with mode: 0644]
chromium_src/chrome/browser/ui/webui/fileicon_source.cc [new file with mode: 0644]
chromium_src/chrome/browser/ui/webui/fileicon_source.h [new file with mode: 0644]
filenames.gypi

index c9e11f7..6fd3415 100644 (file)
@@ -8,15 +8,16 @@
 #include <vector>
 
 #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/gfx_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/callback.h"
 #include "base/base64.h"
 #include "base/files/file_util.h"
 #include "base/strings/pattern.h"
 #include "base/strings/string_util.h"
+#include "chrome/browser/ui/webui/fileicon_source.h"
 #include "native_mate/dictionary.h"
 #include "native_mate/object_template_builder.h"
 #include "net/base/data_url.h"
diff --git a/chromium_src/chrome/browser/icon_loader.cc b/chromium_src/chrome/browser/icon_loader.cc
new file mode 100644 (file)
index 0000000..979ee57
--- /dev/null
@@ -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.
+}
diff --git a/chromium_src/chrome/browser/icon_loader.h b/chromium_src/chrome/browser/icon_loader.h
new file mode 100644 (file)
index 0000000..33301ac
--- /dev/null
@@ -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_
diff --git a/chromium_src/chrome/browser/icon_manager.cc b/chromium_src/chrome/browser/icon_manager.cc
new file mode 100644 (file)
index 0000000..6596ab3
--- /dev/null
@@ -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);
+}
diff --git a/chromium_src/chrome/browser/icon_manager.h b/chromium_src/chrome/browser/icon_manager.h
new file mode 100644 (file)
index 0000000..0b5ec07
--- /dev/null
@@ -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_
diff --git a/chromium_src/chrome/browser/ui/webui/fileicon_source.cc b/chromium_src/chrome/browser/ui/webui/fileicon_source.cc
new file mode 100644 (file)
index 0000000..8659346
--- /dev/null
@@ -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, '=', '&', &parameters);
+  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);
+  }
+}
diff --git a/chromium_src/chrome/browser/ui/webui/fileicon_source.h b/chromium_src/chrome/browser/ui/webui/fileicon_source.h
new file mode 100644 (file)
index 0000000..7fd6671
--- /dev/null
@@ -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_
index 636cbb6..65e74b5 100644 (file)
       'chromium_src/chrome/browser/chrome_process_finder_win.cc',
       'chromium_src/chrome/browser/chrome_process_finder_win.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.h',
       'chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm',
       '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.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.h',
       'chromium_src/chrome/common/chrome_paths.cc',