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 typedef std::pair
<std::string
, std::string
> KVPair
;
67 std::vector
<KVPair
> parameters
;
69 *icon_size
= IconLoader::NORMAL
;
72 base::SplitStringIntoKeyValuePairs(query
, '=', '&', ¶meters
);
73 for (std::vector
<KVPair
>::const_iterator iter
= parameters
.begin();
74 iter
!= parameters
.end(); ++iter
) {
75 if (icon_size
&& iter
->first
== kIconSize
)
76 *icon_size
= SizeStringToIconSize(iter
->second
);
77 else if (scale_factor
&& iter
->first
== kScaleFactor
)
78 webui::ParseScaleFactor(iter
->second
, scale_factor
);
84 FileIconSource::IconRequestDetails::IconRequestDetails() : scale_factor(1.0f
) {
87 FileIconSource::IconRequestDetails::~IconRequestDetails() {
90 FileIconSource::FileIconSource() {}
92 FileIconSource::~FileIconSource() {}
94 void FileIconSource::FetchFileIcon(
95 const base::FilePath
& path
,
97 IconLoader::IconSize icon_size
,
98 const content::URLDataSource::GotDataCallback
& callback
) {
99 IconManager
* im
= g_browser_process
->icon_manager();
100 gfx::Image
* icon
= im
->LookupIconFromFilepath(path
, icon_size
);
103 scoped_refptr
<base::RefCountedBytes
> icon_data(new base::RefCountedBytes
);
104 gfx::PNGCodec::EncodeBGRASkBitmap(
105 icon
->ToImageSkia()->GetRepresentation(scale_factor
).sk_bitmap(),
109 callback
.Run(icon_data
.get());
111 // Attach the ChromeURLDataManager request ID to the history request.
112 IconRequestDetails details
;
113 details
.callback
= callback
;
114 details
.scale_factor
= scale_factor
;
116 // Icon was not in cache, go fetch it slowly.
119 base::Bind(&FileIconSource::OnFileIconDataAvailable
,
120 base::Unretained(this), details
),
121 &cancelable_task_tracker_
);
125 std::string
FileIconSource::GetSource() const {
126 return kFileIconPath
;
129 void FileIconSource::StartDataRequest(
130 const std::string
& url_path
,
131 int render_process_id
,
133 const content::URLDataSource::GotDataCallback
& callback
) {
135 base::FilePath file_path
;
136 IconLoader::IconSize icon_size
;
137 float scale_factor
= 1.0f
;
138 GetFilePathAndQuery(url_path
, &file_path
, &query
);
139 ParseQueryParams(query
, &scale_factor
, &icon_size
);
140 FetchFileIcon(file_path
, scale_factor
, icon_size
, callback
);
143 std::string
FileIconSource::GetMimeType(const std::string
&) const {
144 // Rely on image decoder inferring the correct type.
145 return std::string();
148 void FileIconSource::OnFileIconDataAvailable(const IconRequestDetails
& details
,
151 scoped_refptr
<base::RefCountedBytes
> icon_data(new base::RefCountedBytes
);
152 gfx::PNGCodec::EncodeBGRASkBitmap(
153 icon
->ToImageSkia()->GetRepresentation(
154 details
.scale_factor
).sk_bitmap(),
158 details
.callback
.Run(icon_data
.get());
160 // TODO(glen): send a dummy icon.
161 details
.callback
.Run(NULL
);