1 // Copyright (c) 2011 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.
4
5 #include "chrome/browser/ui/webui/fileicon_source.h"
6
7 #include "base/callback.h"
8 #include "base/file_path.h"
9 #include "base/memory/ref_counted_memory.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/common/time_format.h"
13 #include "grit/generated_resources.h"
14 #include "net/base/escape.h"
15 #include "third_party/skia/include/core/SkBitmap.h"
16 #include "ui/gfx/codec/png_codec.h"
17 #include "ui/gfx/image.h"
18
19 // The path used in internal URLs to file icon data.
20 static const char kFileIconPath[] = "fileicon";
21
FileIconSource()22 FileIconSource::FileIconSource()
23 : DataSource(kFileIconPath, MessageLoop::current()) {}
24
~FileIconSource()25 FileIconSource::~FileIconSource() {
26 cancelable_consumer_.CancelAllRequests();
27 }
28
StartDataRequest(const std::string & path,bool is_incognito,int request_id)29 void FileIconSource::StartDataRequest(const std::string& path,
30 bool is_incognito,
31 int request_id) {
32 std::string escaped_path = UnescapeURLComponent(path, UnescapeRule::SPACES);
33 #if defined(OS_WIN)
34 // The path we receive has the wrong slashes and escaping for what we need;
35 // this only appears to matter for getting icons from .exe files.
36 std::replace(escaped_path.begin(), escaped_path.end(), '/', '\\');
37 FilePath escaped_filepath(UTF8ToWide(escaped_path));
38 #elif defined(OS_POSIX)
39 // The correct encoding on Linux may not actually be UTF8.
40 FilePath escaped_filepath(escaped_path);
41 #endif
42
43 IconManager* im = g_browser_process->icon_manager();
44 gfx::Image* icon = im->LookupIcon(escaped_filepath, IconLoader::NORMAL);
45
46 if (icon) {
47 scoped_refptr<RefCountedBytes> icon_data(new RefCountedBytes);
48 gfx::PNGCodec::EncodeBGRASkBitmap(*icon, false, &icon_data->data);
49
50 SendResponse(request_id, icon_data);
51 } else {
52 // Icon was not in cache, go fetch it slowly.
53 IconManager::Handle h = im->LoadIcon(escaped_filepath,
54 IconLoader::NORMAL,
55 &cancelable_consumer_,
56 NewCallback(this, &FileIconSource::OnFileIconDataAvailable));
57
58 // Attach the ChromeURLDataManager request ID to the history request.
59 cancelable_consumer_.SetClientData(im, h, request_id);
60 }
61 }
62
GetMimeType(const std::string &) const63 std::string FileIconSource::GetMimeType(const std::string&) const {
64 // Rely on image decoder inferring the correct type.
65 return std::string();
66 }
67
OnFileIconDataAvailable(IconManager::Handle handle,gfx::Image * icon)68 void FileIconSource::OnFileIconDataAvailable(IconManager::Handle handle,
69 gfx::Image* icon) {
70 IconManager* im = g_browser_process->icon_manager();
71 int request_id = cancelable_consumer_.GetClientData(im, handle);
72
73 if (icon) {
74 scoped_refptr<RefCountedBytes> icon_data(new RefCountedBytes);
75 gfx::PNGCodec::EncodeBGRASkBitmap(*icon, false, &icon_data->data);
76
77 SendResponse(request_id, icon_data);
78 } else {
79 // TODO(glen): send a dummy icon.
80 SendResponse(request_id, NULL);
81 }
82 }
83