Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / extensions / api / file_handlers / mime_util.cc
blob74b622c26bdf7ec03b792d0d409553995be20d29
1 // Copyright 2013 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/extensions/api/file_handlers/mime_util.h"
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "net/base/filename_util.h"
12 #include "net/base/mime_sniffer.h"
13 #include "net/base/mime_util.h"
14 #include "storage/browser/fileapi/file_system_url.h"
16 #if defined(OS_CHROMEOS)
17 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
18 #endif
20 using content::BrowserThread;
22 namespace extensions {
23 namespace app_file_handler_util {
24 namespace {
26 // Detects MIME type by reading initial bytes from the file. If found, then
27 // writes the MIME type to |result|.
28 void SniffMimeType(const base::FilePath& local_path, std::string* result) {
29 std::vector<char> content(net::kMaxBytesToSniff);
31 const int bytes_read =
32 base::ReadFile(local_path, &content[0], content.size());
34 if (bytes_read >= 0) {
35 net::SniffMimeType(&content[0],
36 bytes_read,
37 net::FilePathToFileURL(local_path),
38 std::string(), // type_hint (passes no hint)
39 result);
43 #if defined(OS_CHROMEOS)
44 // Converts a result passed as a scoped pointer to a dereferenced value passed
45 // to |callback|.
46 void OnGetMimeTypeFromFileForNonNativeLocalPathCompleted(
47 scoped_ptr<std::string> mime_type,
48 const base::Callback<void(const std::string&)>& callback) {
49 callback.Run(*mime_type);
52 // Called when fetching MIME type for a non-native local path is completed.
53 // If |success| is false, then tries to guess the MIME type by looking at the
54 // file name.
55 void OnGetMimeTypeFromMetadataForNonNativeLocalPathCompleted(
56 const base::FilePath& local_path,
57 const base::Callback<void(const std::string&)>& callback,
58 bool success,
59 const std::string& mime_type) {
60 if (success) {
61 callback.Run(mime_type);
62 return;
65 // MIME type not available with metadata, hence try to guess it from the
66 // file's extension.
67 scoped_ptr<std::string> mime_type_from_extension(new std::string);
68 std::string* const mime_type_from_extension_ptr =
69 mime_type_from_extension.get();
70 BrowserThread::PostBlockingPoolTaskAndReply(
71 FROM_HERE,
72 base::Bind(base::IgnoreResult(&net::GetMimeTypeFromFile),
73 local_path,
74 mime_type_from_extension_ptr),
75 base::Bind(&OnGetMimeTypeFromFileForNonNativeLocalPathCompleted,
76 base::Passed(&mime_type_from_extension),
77 callback));
79 #endif
81 // Called when sniffing for MIME type in the native local file is completed.
82 void OnSniffMimeTypeForNativeLocalPathCompleted(
83 scoped_ptr<std::string> mime_type,
84 const base::Callback<void(const std::string&)>& callback) {
85 callback.Run(*mime_type);
88 } // namespace
90 // Handles response of net::GetMimeTypeFromFile for native file systems. If
91 // MIME type is available, then forwards it to |callback|. Otherwise, fallbacks
92 // to sniffing.
93 void OnGetMimeTypeFromFileForNativeLocalPathCompleted(
94 const base::FilePath& local_path,
95 scoped_ptr<std::string> mime_type,
96 const base::Callback<void(const std::string&)>& callback) {
97 if (!mime_type->empty()) {
98 callback.Run(*mime_type);
99 return;
102 scoped_ptr<std::string> sniffed_mime_type(new std::string);
103 std::string* const sniffed_mime_type_ptr = sniffed_mime_type.get();
104 BrowserThread::PostBlockingPoolTaskAndReply(
105 FROM_HERE,
106 base::Bind(&SniffMimeType, local_path, sniffed_mime_type_ptr),
107 base::Bind(&OnSniffMimeTypeForNativeLocalPathCompleted,
108 base::Passed(&sniffed_mime_type),
109 callback));
112 // Fetches MIME type for a local path and returns it with a |callback|.
113 void GetMimeTypeForLocalPath(
114 Profile* profile,
115 const base::FilePath& local_path,
116 const base::Callback<void(const std::string&)>& callback) {
117 #if defined(OS_CHROMEOS)
118 if (file_manager::util::IsUnderNonNativeLocalPath(profile, local_path)) {
119 // For non-native files, try to get the MIME type from metadata. If not
120 // available, then try to guess from the extension. Never sniff (because
121 // it can be very slow).
122 file_manager::util::GetNonNativeLocalPathMimeType(
123 profile,
124 local_path,
125 base::Bind(&OnGetMimeTypeFromMetadataForNonNativeLocalPathCompleted,
126 local_path,
127 callback));
128 return;
130 #endif
132 // For native local files, try to guess the mime from the extension. If
133 // not available, then try to sniff if.
134 scoped_ptr<std::string> mime_type_from_extension(new std::string);
135 std::string* const mime_type_from_extension_ptr =
136 mime_type_from_extension.get();
137 BrowserThread::PostBlockingPoolTaskAndReply(
138 FROM_HERE,
139 base::Bind(base::IgnoreResult(&net::GetMimeTypeFromFile),
140 local_path,
141 mime_type_from_extension_ptr),
142 base::Bind(&OnGetMimeTypeFromFileForNativeLocalPathCompleted,
143 local_path,
144 base::Passed(&mime_type_from_extension),
145 callback));
148 MimeTypeCollector::MimeTypeCollector(Profile* profile)
149 : profile_(profile), left_(0), weak_ptr_factory_(this) {
152 MimeTypeCollector::~MimeTypeCollector() {
155 void MimeTypeCollector::CollectForURLs(
156 const std::vector<storage::FileSystemURL>& urls,
157 const CompletionCallback& callback) {
158 std::vector<base::FilePath> local_paths;
159 for (size_t i = 0; i < urls.size(); ++i) {
160 local_paths.push_back(urls[i].path());
163 CollectForLocalPaths(local_paths, callback);
166 void MimeTypeCollector::CollectForLocalPaths(
167 const std::vector<base::FilePath>& local_paths,
168 const CompletionCallback& callback) {
169 DCHECK(!callback.is_null());
170 callback_ = callback;
172 DCHECK(!result_.get());
173 result_.reset(new std::vector<std::string>(local_paths.size()));
174 left_ = local_paths.size();
176 if (!left_) {
177 // Nothing to process.
178 base::MessageLoopProxy::current()->PostTask(
179 FROM_HERE, base::Bind(callback_, base::Passed(&result_)));
180 callback_ = CompletionCallback();
181 return;
184 for (size_t i = 0; i < local_paths.size(); ++i) {
185 GetMimeTypeForLocalPath(profile_,
186 local_paths[i],
187 base::Bind(&MimeTypeCollector::OnMimeTypeCollected,
188 weak_ptr_factory_.GetWeakPtr(),
189 i));
193 void MimeTypeCollector::OnMimeTypeCollected(size_t index,
194 const std::string& mime_type) {
195 (*result_)[index] = mime_type;
196 if (!--left_) {
197 base::MessageLoopProxy::current()->PostTask(
198 FROM_HERE, base::Bind(callback_, base::Passed(&result_)));
199 // Release the callback to avoid a circullar reference in case an instance
200 // of this class is a member of a ref counted class, which instance is bound
201 // to this callback.
202 callback_ = CompletionCallback();
206 } // namespace app_file_handler_util
207 } // namespace extensions