blob: af8135a5b6ee661eb5298457b5fbb0ff373b5a6d [file] [log] [blame]
[email protected]25cc7502012-01-31 19:33:551// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]12e14fc2009-02-19 22:25:222// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]fd42ac30f2011-02-27 19:33:365#include "chrome/browser/ui/webui/fileicon_source.h"
[email protected]12e14fc2009-02-19 22:25:226
[email protected]25cc7502012-01-31 19:33:557#include "base/basictypes.h"
[email protected]c1896982012-12-05 20:26:178#include "base/bind.h"
[email protected]2041cf342010-02-19 03:15:599#include "base/callback.h"
[email protected]864b1362010-08-19 03:49:3810#include "base/file_path.h"
[email protected]3b63f8f42011-03-28 01:54:1511#include "base/memory/ref_counted_memory.h"
[email protected]c1896982012-12-05 20:26:1712#include "base/message_loop.h"
[email protected]25cc7502012-01-31 19:33:5513#include "base/string_split.h"
[email protected]d55194ca2010-03-11 18:25:4514#include "base/utf_string_conversions.h"
[email protected]12e14fc2009-02-19 22:25:2215#include "chrome/browser/browser_process.h"
[email protected]12e14fc2009-02-19 22:25:2216#include "chrome/common/time_format.h"
[email protected]25cc7502012-01-31 19:33:5517#include "googleurl/src/gurl.h"
[email protected]6c5a7c72009-02-25 00:57:4318#include "grit/generated_resources.h"
[email protected]43437692009-03-04 04:07:3419#include "net/base/escape.h"
[email protected]66171ab2011-03-03 15:50:0720#include "third_party/skia/include/core/SkBitmap.h"
[email protected]08397d52011-02-05 01:53:3821#include "ui/gfx/codec/png_codec.h"
[email protected]f08e0512011-06-13 18:10:4422#include "ui/gfx/image/image.h"
[email protected]daf19c52012-07-13 19:01:3223#include "ui/gfx/image/image_skia.h"
[email protected]5053d402013-01-23 05:19:2624#include "ui/webui/web_ui_util.h"
[email protected]12e14fc2009-02-19 22:25:2225
[email protected]25cc7502012-01-31 19:33:5526namespace {
27
28typedef std::map<std::string, IconLoader::IconSize> QueryIconSizeMap;
29
[email protected]12e14fc2009-02-19 22:25:2230// The path used in internal URLs to file icon data.
[email protected]25cc7502012-01-31 19:33:5531const char kFileIconPath[] = "fileicon";
32
33// URL parameter specifying icon size.
34const char kIconSize[] = "iconsize";
35
[email protected]daf19c52012-07-13 19:01:3236// URL parameter specifying scale factor.
37const char kScaleFactor[] = "scale";
38
[email protected]25cc7502012-01-31 19:33:5539// Assuming the url is of the form '/path?query', convert the path portion into
40// a FilePath and return the resulting |file_path| and |query|. The path
41// portion may have been encoded using encodeURIComponent().
42void GetFilePathAndQuery(const std::string& url,
[email protected]650b2d52013-02-10 03:41:4543 base::FilePath* file_path,
[email protected]25cc7502012-01-31 19:33:5544 std::string* query) {
45 // We receive the url with chrome://fileicon/ stripped but GURL expects it.
46 const GURL gurl("chrome://fileicon/" + url);
[email protected]daf19c52012-07-13 19:01:3247 std::string path = net::UnescapeURLComponent(
48 gurl.path().substr(1), (net::UnescapeRule::URL_SPECIAL_CHARS |
49 net::UnescapeRule::SPACES));
50
[email protected]25cc7502012-01-31 19:33:5551#if defined(OS_WIN)
52 // The path we receive has the wrong slashes and escaping for what we need;
53 // this only appears to matter for getting icons from .exe files.
54 std::replace(path.begin(), path.end(), '/', '\\');
[email protected]650b2d52013-02-10 03:41:4555 *file_path = base::FilePath(UTF8ToWide(path));
[email protected]25cc7502012-01-31 19:33:5556#elif defined(OS_POSIX)
57 // The correct encoding on Linux may not actually be UTF8.
[email protected]650b2d52013-02-10 03:41:4558 *file_path = base::FilePath(path);
[email protected]25cc7502012-01-31 19:33:5559#endif
60 query->assign(gurl.query());
61}
62
63IconLoader::IconSize SizeStringToIconSize(const std::string& size_string) {
64 if (size_string == "small") return IconLoader::SMALL;
65 if (size_string == "large") return IconLoader::LARGE;
66 // We default to NORMAL if we don't recognize the size_string. Including
67 // size_string=="normal".
68 return IconLoader::NORMAL;
69}
70
71// Simple parser for data on the query.
[email protected]daf19c52012-07-13 19:01:3272void ParseQueryParams(const std::string& query,
73 ui::ScaleFactor* scale_factor,
74 IconLoader::IconSize* icon_size) {
[email protected]25cc7502012-01-31 19:33:5575 typedef std::pair<std::string, std::string> KVPair;
76 std::vector<KVPair> parameters;
[email protected]daf19c52012-07-13 19:01:3277 if (icon_size)
78 *icon_size = IconLoader::NORMAL;
79 if (scale_factor)
[email protected]0a4cf452012-11-14 07:28:4080 *scale_factor = ui::SCALE_FACTOR_100P;
[email protected]25cc7502012-01-31 19:33:5581 base::SplitStringIntoKeyValuePairs(query, '=', '&', &parameters);
82 for (std::vector<KVPair>::const_iterator iter = parameters.begin();
83 iter != parameters.end(); ++iter) {
[email protected]daf19c52012-07-13 19:01:3284 if (icon_size && iter->first == kIconSize)
85 *icon_size = SizeStringToIconSize(iter->second);
86 else if (scale_factor && iter->first == kScaleFactor)
[email protected]5053d402013-01-23 05:19:2687 webui::ParseScaleFactor(iter->second, scale_factor);
[email protected]25cc7502012-01-31 19:33:5588 }
[email protected]25cc7502012-01-31 19:33:5589}
90
91} // namespace
[email protected]12e14fc2009-02-19 22:25:2292
[email protected]90d9f1e2013-01-16 02:46:4193FileIconSource::IconRequestDetails::IconRequestDetails() {
94}
95
96FileIconSource::IconRequestDetails::~IconRequestDetails() {
97}
98
[email protected]92253622013-01-14 20:40:5099FileIconSource::FileIconSource() {}
[email protected]12e14fc2009-02-19 22:25:22100
[email protected]c1896982012-12-05 20:26:17101FileIconSource::~FileIconSource() {}
[email protected]12e14fc2009-02-19 22:25:22102
[email protected]90d9f1e2013-01-16 02:46:41103void FileIconSource::FetchFileIcon(
[email protected]650b2d52013-02-10 03:41:45104 const base::FilePath& path,
[email protected]90d9f1e2013-01-16 02:46:41105 ui::ScaleFactor scale_factor,
106 IconLoader::IconSize icon_size,
107 const content::URLDataSource::GotDataCallback& callback) {
[email protected]66171ab2011-03-03 15:50:07108 IconManager* im = g_browser_process->icon_manager();
[email protected]25cc7502012-01-31 19:33:55109 gfx::Image* icon = im->LookupIcon(path, icon_size);
[email protected]12e14fc2009-02-19 22:25:22110
111 if (icon) {
[email protected]ebbccb952012-04-20 09:51:31112 scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
[email protected]daf19c52012-07-13 19:01:32113 gfx::PNGCodec::EncodeBGRASkBitmap(
114 icon->ToImageSkia()->GetRepresentation(scale_factor).sk_bitmap(),
115 false, &icon_data->data());
[email protected]12e14fc2009-02-19 22:25:22116
[email protected]90d9f1e2013-01-16 02:46:41117 callback.Run(icon_data);
[email protected]12e14fc2009-02-19 22:25:22118 } else {
[email protected]12e14fc2009-02-19 22:25:22119 // Attach the ChromeURLDataManager request ID to the history request.
[email protected]daf19c52012-07-13 19:01:32120 IconRequestDetails details;
[email protected]90d9f1e2013-01-16 02:46:41121 details.callback = callback;
[email protected]daf19c52012-07-13 19:01:32122 details.scale_factor = scale_factor;
[email protected]c1896982012-12-05 20:26:17123
124 // Icon was not in cache, go fetch it slowly.
125 im->LoadIcon(path,
126 icon_size,
127 base::Bind(&FileIconSource::OnFileIconDataAvailable,
128 base::Unretained(this), details),
129 &cancelable_task_tracker_);
[email protected]12e14fc2009-02-19 22:25:22130 }
131}
132
[email protected]92253622013-01-14 20:40:50133std::string FileIconSource::GetSource() {
134 return kFileIconPath;
135}
136
[email protected]90d9f1e2013-01-16 02:46:41137void FileIconSource::StartDataRequest(
138 const std::string& url_path,
139 bool is_incognito,
140 const content::URLDataSource::GotDataCallback& callback) {
[email protected]25cc7502012-01-31 19:33:55141 std::string query;
[email protected]650b2d52013-02-10 03:41:45142 base::FilePath file_path;
[email protected]daf19c52012-07-13 19:01:32143 ui::ScaleFactor scale_factor;
144 IconLoader::IconSize icon_size;
[email protected]25cc7502012-01-31 19:33:55145 GetFilePathAndQuery(url_path, &file_path, &query);
[email protected]daf19c52012-07-13 19:01:32146 ParseQueryParams(query, &scale_factor, &icon_size);
[email protected]90d9f1e2013-01-16 02:46:41147 FetchFileIcon(file_path, scale_factor, icon_size, callback);
[email protected]25cc7502012-01-31 19:33:55148}
149
[email protected]e4be2dd2010-12-14 00:44:39150std::string FileIconSource::GetMimeType(const std::string&) const {
151 // Rely on image decoder inferring the correct type.
152 return std::string();
153}
154
[email protected]c1896982012-12-05 20:26:17155void FileIconSource::OnFileIconDataAvailable(const IconRequestDetails& details,
[email protected]66171ab2011-03-03 15:50:07156 gfx::Image* icon) {
[email protected]12e14fc2009-02-19 22:25:22157 if (icon) {
[email protected]ebbccb952012-04-20 09:51:31158 scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
[email protected]daf19c52012-07-13 19:01:32159 gfx::PNGCodec::EncodeBGRASkBitmap(
[email protected]c1896982012-12-05 20:26:17160 icon->ToImageSkia()->GetRepresentation(details.scale_factor)
161 .sk_bitmap(),
162 false,
163 &icon_data->data());
[email protected]12e14fc2009-02-19 22:25:22164
[email protected]90d9f1e2013-01-16 02:46:41165 details.callback.Run(icon_data);
[email protected]12e14fc2009-02-19 22:25:22166 } else {
167 // TODO(glen): send a dummy icon.
[email protected]90d9f1e2013-01-16 02:46:41168 details.callback.Run(NULL);
[email protected]12e14fc2009-02-19 22:25:22169 }
[email protected]f0a51fb52009-03-05 12:46:38170}