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"
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"
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
,
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
,
65 IconLoader::IconSize
* icon_size
) {
66 base::StringPairs parameters
;
68 *icon_size
= IconLoader::NORMAL
;
71 base::SplitStringIntoKeyValuePairs(query
, '=', '&', ¶meters
);
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
);
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
,
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
);
102 scoped_refptr
<base::RefCountedBytes
> icon_data(new base::RefCountedBytes
);
103 gfx::PNGCodec::EncodeBGRASkBitmap(
104 icon
->ToImageSkia()->GetRepresentation(scale_factor
).sk_bitmap(),
108 callback
.Run(icon_data
.get());
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.
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
,
132 const content::URLDataSource::GotDataCallback
& callback
) {
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
,
150 scoped_refptr
<base::RefCountedBytes
> icon_data(new base::RefCountedBytes
);
151 gfx::PNGCodec::EncodeBGRASkBitmap(
152 icon
->ToImageSkia()->GetRepresentation(
153 details
.scale_factor
).sk_bitmap(),
157 details
.callback
.Run(icon_data
.get());
159 // TODO(glen): send a dummy icon.
160 details
.callback
.Run(NULL
);