Add ability to gather metrics to BubbleManager.
[chromium-blink-merge.git] / chrome / browser / ui / webui / fileicon_source.cc
blob923656521d599d1e9e5366cee4ac713caa7e3389
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/webui/fileicon_source.h"
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/ref_counted_memory.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/browser_process.h"
16 #include "net/base/escape.h"
17 #include "third_party/skia/include/core/SkBitmap.h"
18 #include "ui/base/webui/web_ui_util.h"
19 #include "ui/gfx/codec/png_codec.h"
20 #include "ui/gfx/image/image.h"
21 #include "ui/gfx/image/image_skia.h"
22 #include "url/gurl.h"
24 namespace {
26 typedef std::map<std::string, IconLoader::IconSize> QueryIconSizeMap;
28 // The path used in internal URLs to file icon data.
29 const char kFileIconPath[] = "fileicon";
31 // URL parameter specifying icon size.
32 const char kIconSize[] = "iconsize";
34 // URL parameter specifying scale factor.
35 const char kScaleFactor[] = "scale";
37 // Assuming the url is of the form '/path?query', convert the path portion into
38 // a FilePath and return the resulting |file_path| and |query|. The path
39 // portion may have been encoded using encodeURIComponent().
40 void GetFilePathAndQuery(const std::string& url,
41 base::FilePath* file_path,
42 std::string* query) {
43 // We receive the url with chrome://fileicon/ stripped but GURL expects it.
44 const GURL gurl("chrome://fileicon/" + url);
45 std::string path = net::UnescapeURLComponent(
46 gurl.path().substr(1), (net::UnescapeRule::URL_SPECIAL_CHARS |
47 net::UnescapeRule::SPACES));
49 *file_path = base::FilePath::FromUTF8Unsafe(path);
50 *file_path = file_path->NormalizePathSeparators();
51 query->assign(gurl.query());
54 IconLoader::IconSize SizeStringToIconSize(const std::string& size_string) {
55 if (size_string == "small") return IconLoader::SMALL;
56 if (size_string == "large") return IconLoader::LARGE;
57 // We default to NORMAL if we don't recognize the size_string. Including
58 // size_string=="normal".
59 return IconLoader::NORMAL;
62 // Simple parser for data on the query.
63 void ParseQueryParams(const std::string& query,
64 float* scale_factor,
65 IconLoader::IconSize* icon_size) {
66 base::StringPairs parameters;
67 if (icon_size)
68 *icon_size = IconLoader::NORMAL;
69 if (scale_factor)
70 *scale_factor = 1.0f;
71 base::SplitStringIntoKeyValuePairs(query, '=', '&', &parameters);
72 for (base::StringPairs::const_iterator iter = parameters.begin();
73 iter != parameters.end(); ++iter) {
74 if (icon_size && iter->first == kIconSize)
75 *icon_size = SizeStringToIconSize(iter->second);
76 else if (scale_factor && iter->first == kScaleFactor)
77 webui::ParseScaleFactor(iter->second, scale_factor);
81 } // namespace
83 FileIconSource::IconRequestDetails::IconRequestDetails() : scale_factor(1.0f) {
86 FileIconSource::IconRequestDetails::~IconRequestDetails() {
89 FileIconSource::FileIconSource() {}
91 FileIconSource::~FileIconSource() {}
93 void FileIconSource::FetchFileIcon(
94 const base::FilePath& path,
95 float scale_factor,
96 IconLoader::IconSize icon_size,
97 const content::URLDataSource::GotDataCallback& callback) {
98 IconManager* im = g_browser_process->icon_manager();
99 gfx::Image* icon = im->LookupIconFromFilepath(path, icon_size);
101 if (icon) {
102 scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
103 gfx::PNGCodec::EncodeBGRASkBitmap(
104 icon->ToImageSkia()->GetRepresentation(scale_factor).sk_bitmap(),
105 false,
106 &icon_data->data());
108 callback.Run(icon_data.get());
109 } else {
110 // Attach the ChromeURLDataManager request ID to the history request.
111 IconRequestDetails details;
112 details.callback = callback;
113 details.scale_factor = scale_factor;
115 // Icon was not in cache, go fetch it slowly.
116 im->LoadIcon(path,
117 icon_size,
118 base::Bind(&FileIconSource::OnFileIconDataAvailable,
119 base::Unretained(this), details),
120 &cancelable_task_tracker_);
124 std::string FileIconSource::GetSource() const {
125 return kFileIconPath;
128 void FileIconSource::StartDataRequest(
129 const std::string& url_path,
130 int render_process_id,
131 int render_frame_id,
132 const content::URLDataSource::GotDataCallback& callback) {
133 std::string query;
134 base::FilePath file_path;
135 IconLoader::IconSize icon_size;
136 float scale_factor = 1.0f;
137 GetFilePathAndQuery(url_path, &file_path, &query);
138 ParseQueryParams(query, &scale_factor, &icon_size);
139 FetchFileIcon(file_path, scale_factor, icon_size, callback);
142 std::string FileIconSource::GetMimeType(const std::string&) const {
143 // Rely on image decoder inferring the correct type.
144 return std::string();
147 void FileIconSource::OnFileIconDataAvailable(const IconRequestDetails& details,
148 gfx::Image* icon) {
149 if (icon) {
150 scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
151 gfx::PNGCodec::EncodeBGRASkBitmap(
152 icon->ToImageSkia()->GetRepresentation(
153 details.scale_factor).sk_bitmap(),
154 false,
155 &icon_data->data());
157 details.callback.Run(icon_data.get());
158 } else {
159 // TODO(glen): send a dummy icon.
160 details.callback.Run(NULL);