Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(558)

Side by Side Diff: extensions/browser/api/file_handlers/mime_util.cc

Issue 2685883008: Revert of Move file_handlers API from //chrome to //extensions (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "extensions/browser/api/file_handlers/mime_util.h"
6
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "base/threading/thread_task_runner_handle.h"
10 #include "build/build_config.h"
11 #include "content/public/browser/browser_context.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "net/base/filename_util.h"
14 #include "net/base/mime_sniffer.h"
15 #include "net/base/mime_util.h"
16 #include "storage/browser/fileapi/file_system_url.h"
17
18 #if defined(OS_CHROMEOS)
19 #include "extensions/browser/api/extensions_api_client.h"
20 #include "extensions/browser/api/file_handlers/non_native_file_system_delegate.h "
21 #endif
22
23 using content::BrowserThread;
24
25 namespace {
26
27 const char kMimeTypeApplicationOctetStream[] = "application/octet-stream";
28
29 } // namespace
30
31 namespace extensions {
32 namespace app_file_handler_util {
33 namespace {
34
35 // Detects MIME type by reading initial bytes from the file. If found, then
36 // writes the MIME type to |result|.
37 void SniffMimeType(const base::FilePath& local_path, std::string* result) {
38 std::vector<char> content(net::kMaxBytesToSniff);
39
40 const int bytes_read =
41 base::ReadFile(local_path, &content[0], static_cast<int>(content.size()));
42
43 if (bytes_read >= 0) {
44 net::SniffMimeType(&content[0], bytes_read,
45 net::FilePathToFileURL(local_path),
46 std::string(), // type_hint (passes no hint)
47 result);
48 }
49 }
50
51 #if defined(OS_CHROMEOS)
52 // Converts a result passed as a scoped pointer to a dereferenced value passed
53 // to |callback|.
54 void OnGetMimeTypeFromFileForNonNativeLocalPathCompleted(
55 std::unique_ptr<std::string> mime_type,
56 const base::Callback<void(const std::string&)>& callback) {
57 callback.Run(*mime_type);
58 }
59
60 // Called when fetching MIME type for a non-native local path is completed.
61 // If |success| is false, then tries to guess the MIME type by looking at the
62 // file name.
63 void OnGetMimeTypeFromMetadataForNonNativeLocalPathCompleted(
64 const base::FilePath& local_path,
65 const base::Callback<void(const std::string&)>& callback,
66 bool success,
67 const std::string& mime_type) {
68 if (success) {
69 callback.Run(mime_type);
70 return;
71 }
72
73 // MIME type not available with metadata, hence try to guess it from the
74 // file's extension.
75 std::unique_ptr<std::string> mime_type_from_extension(new std::string);
76 std::string* const mime_type_from_extension_ptr =
77 mime_type_from_extension.get();
78 BrowserThread::PostBlockingPoolTaskAndReply(
79 FROM_HERE, base::Bind(base::IgnoreResult(&net::GetMimeTypeFromFile),
80 local_path, mime_type_from_extension_ptr),
81 base::Bind(&OnGetMimeTypeFromFileForNonNativeLocalPathCompleted,
82 base::Passed(&mime_type_from_extension), callback));
83 }
84 #endif
85
86 // Called when sniffing for MIME type in the native local file is completed.
87 void OnSniffMimeTypeForNativeLocalPathCompleted(
88 std::unique_ptr<std::string> mime_type,
89 const base::Callback<void(const std::string&)>& callback) {
90 // Do not return application/zip as sniffed result. If the file has .zip
91 // extension, it should be already returned as application/zip. If the file
92 // does not have .zip extension and couldn't find mime type from the
93 // extension, it might be unknown internally zipped file.
94 if (*mime_type == "application/zip") {
95 callback.Run(kMimeTypeApplicationOctetStream);
96 return;
97 }
98
99 callback.Run(*mime_type);
100 }
101
102 } // namespace
103
104 // Handles response of net::GetMimeTypeFromFile for native file systems. If
105 // MIME type is available, then forwards it to |callback|. Otherwise, fallbacks
106 // to sniffing.
107 void OnGetMimeTypeFromFileForNativeLocalPathCompleted(
108 const base::FilePath& local_path,
109 std::unique_ptr<std::string> mime_type,
110 const base::Callback<void(const std::string&)>& callback) {
111 if (!mime_type->empty()) {
112 callback.Run(*mime_type);
113 return;
114 }
115
116 std::unique_ptr<std::string> sniffed_mime_type(
117 new std::string(kMimeTypeApplicationOctetStream));
118 std::string* const sniffed_mime_type_ptr = sniffed_mime_type.get();
119 BrowserThread::PostBlockingPoolTaskAndReply(
120 FROM_HERE, base::Bind(&SniffMimeType, local_path, sniffed_mime_type_ptr),
121 base::Bind(&OnSniffMimeTypeForNativeLocalPathCompleted,
122 base::Passed(&sniffed_mime_type), callback));
123 }
124
125 // Fetches MIME type for a local path and returns it with a |callback|.
126 void GetMimeTypeForLocalPath(
127 content::BrowserContext* context,
128 const base::FilePath& local_path,
129 const base::Callback<void(const std::string&)>& callback) {
130 #if defined(OS_CHROMEOS)
131 NonNativeFileSystemDelegate* delegate =
132 ExtensionsAPIClient::Get()->GetNonNativeFileSystemDelegate();
133 if (delegate && delegate->IsUnderNonNativeLocalPath(context, local_path)) {
134 // For non-native files, try to get the MIME type from metadata. If not
135 // available, then try to guess from the extension. Never sniff (because
136 // it can be very slow).
137 delegate->GetNonNativeLocalPathMimeType(
138 context, local_path,
139 base::Bind(&OnGetMimeTypeFromMetadataForNonNativeLocalPathCompleted,
140 local_path, callback));
141 return;
142 }
143 #endif
144
145 // For native local files, try to guess the mime from the extension. If
146 // not available, then try to sniff if.
147 std::unique_ptr<std::string> mime_type_from_extension(new std::string);
148 std::string* const mime_type_from_extension_ptr =
149 mime_type_from_extension.get();
150 BrowserThread::PostBlockingPoolTaskAndReply(
151 FROM_HERE, base::Bind(base::IgnoreResult(&net::GetMimeTypeFromFile),
152 local_path, mime_type_from_extension_ptr),
153 base::Bind(&OnGetMimeTypeFromFileForNativeLocalPathCompleted, local_path,
154 base::Passed(&mime_type_from_extension), callback));
155 }
156
157 MimeTypeCollector::MimeTypeCollector(content::BrowserContext* context)
158 : context_(context), left_(0), weak_ptr_factory_(this) {}
159
160 MimeTypeCollector::~MimeTypeCollector() {}
161
162 void MimeTypeCollector::CollectForURLs(
163 const std::vector<storage::FileSystemURL>& urls,
164 const CompletionCallback& callback) {
165 std::vector<base::FilePath> local_paths;
166 for (size_t i = 0; i < urls.size(); ++i) {
167 local_paths.push_back(urls[i].path());
168 }
169
170 CollectForLocalPaths(local_paths, callback);
171 }
172
173 void MimeTypeCollector::CollectForLocalPaths(
174 const std::vector<base::FilePath>& local_paths,
175 const CompletionCallback& callback) {
176 DCHECK(!callback.is_null());
177 callback_ = callback;
178
179 DCHECK(!result_.get());
180 result_.reset(new std::vector<std::string>(local_paths.size()));
181 left_ = local_paths.size();
182
183 if (!left_) {
184 // Nothing to process.
185 base::ThreadTaskRunnerHandle::Get()->PostTask(
186 FROM_HERE, base::Bind(callback_, base::Passed(&result_)));
187 callback_ = CompletionCallback();
188 return;
189 }
190
191 for (size_t i = 0; i < local_paths.size(); ++i) {
192 GetMimeTypeForLocalPath(context_, local_paths[i],
193 base::Bind(&MimeTypeCollector::OnMimeTypeCollected,
194 weak_ptr_factory_.GetWeakPtr(), i));
195 }
196 }
197
198 void MimeTypeCollector::OnMimeTypeCollected(size_t index,
199 const std::string& mime_type) {
200 (*result_)[index] = mime_type;
201 if (!--left_) {
202 base::ThreadTaskRunnerHandle::Get()->PostTask(
203 FROM_HERE, base::Bind(callback_, base::Passed(&result_)));
204 // Release the callback to avoid a circullar reference in case an instance
205 // of this class is a member of a ref counted class, which instance is bound
206 // to this callback.
207 callback_ = CompletionCallback();
208 }
209 }
210
211 } // namespace app_file_handler_util
212 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/api/file_handlers/mime_util.h ('k') | extensions/browser/api/file_handlers/mime_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698