Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / chromeos / file_manager / filesystem_api_util.cc
blobb97071f3cab01c93d04cf943cb97a9b61016ca2c
1 // Copyright 2014 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/chromeos/file_manager/filesystem_api_util.h"
7 #include "base/callback.h"
8 #include "base/files/file.h"
9 #include "base/files/file_path.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "chrome/browser/chromeos/drive/file_system_util.h"
12 #include "chrome/browser/chromeos/file_manager/app_id.h"
13 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
14 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
15 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
16 #include "chrome/browser/extensions/extension_util.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "components/drive/file_errors.h"
19 #include "components/drive/file_system_core_util.h"
20 #include "components/drive/file_system_interface.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/storage_partition.h"
23 #include "google_apis/drive/task_util.h"
24 #include "storage/browser/fileapi/file_system_context.h"
26 namespace file_manager {
27 namespace util {
28 namespace {
30 // Helper function used to implement GetNonNativeLocalPathMimeType. It extracts
31 // the mime type from the passed Drive resource entry.
32 void GetMimeTypeAfterGetResourceEntryForDrive(
33 const base::Callback<void(bool, const std::string&)>& callback,
34 drive::FileError error,
35 scoped_ptr<drive::ResourceEntry> entry) {
36 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
38 if (error != drive::FILE_ERROR_OK || !entry->has_file_specific_info() ||
39 entry->file_specific_info().content_mime_type().empty()) {
40 callback.Run(false, std::string());
41 return;
43 callback.Run(true, entry->file_specific_info().content_mime_type());
46 // Helper function used to implement GetNonNativeLocalPathMimeType. It extracts
47 // the mime type from the passed metadata from a providing extension.
48 void GetMimeTypeAfterGetMetadataForProvidedFileSystem(
49 const base::Callback<void(bool, const std::string&)>& callback,
50 scoped_ptr<chromeos::file_system_provider::EntryMetadata> metadata,
51 base::File::Error result) {
52 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
54 if (result != base::File::FILE_OK || metadata->mime_type.empty()) {
55 callback.Run(false, std::string());
56 return;
58 callback.Run(true, metadata->mime_type);
61 // Helper function to converts a callback that takes boolean value to that takes
62 // File::Error, by regarding FILE_OK as the only successful value.
63 void BoolCallbackAsFileErrorCallback(
64 const base::Callback<void(bool)>& callback,
65 base::File::Error error) {
66 return callback.Run(error == base::File::FILE_OK);
69 // Part of PrepareFileOnIOThread. It tries to create a new file if the given
70 // |url| is not already inhabited.
71 void PrepareFileAfterCheckExistOnIOThread(
72 scoped_refptr<storage::FileSystemContext> file_system_context,
73 const storage::FileSystemURL& url,
74 const storage::FileSystemOperation::StatusCallback& callback,
75 base::File::Error error) {
76 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
78 if (error != base::File::FILE_ERROR_NOT_FOUND) {
79 callback.Run(error);
80 return;
83 // Call with the second argument |exclusive| set to false, meaning that it
84 // is not an error even if the file already exists (it can happen if the file
85 // is created after the previous FileExists call and before this CreateFile.)
87 // Note that the preceding call to FileExists is necessary for handling
88 // read only filesystems that blindly rejects handling CreateFile().
89 file_system_context->operation_runner()->CreateFile(url, false, callback);
92 // Checks whether a file exists at the given |url|, and try creating it if it
93 // is not already there.
94 void PrepareFileOnIOThread(
95 scoped_refptr<storage::FileSystemContext> file_system_context,
96 const storage::FileSystemURL& url,
97 const base::Callback<void(bool)>& callback) {
98 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
100 file_system_context->operation_runner()->FileExists(
101 url,
102 base::Bind(&PrepareFileAfterCheckExistOnIOThread,
103 file_system_context,
104 url,
105 base::Bind(&BoolCallbackAsFileErrorCallback, callback)));
108 } // namespace
110 bool IsNonNativeFileSystemType(storage::FileSystemType type) {
111 switch (type) {
112 case storage::kFileSystemTypeNativeLocal:
113 case storage::kFileSystemTypeRestrictedNativeLocal:
114 return false;
115 default:
116 // The path indeed corresponds to a mount point not associated with a
117 // native local path.
118 return true;
122 bool IsUnderNonNativeLocalPath(Profile* profile,
123 const base::FilePath& path) {
124 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
126 GURL url;
127 if (!util::ConvertAbsoluteFilePathToFileSystemUrl(
128 profile, path, kFileManagerAppId, &url)) {
129 return false;
132 storage::FileSystemURL filesystem_url =
133 GetFileSystemContextForExtensionId(profile, kFileManagerAppId)
134 ->CrackURL(url);
135 if (!filesystem_url.is_valid())
136 return false;
138 return IsNonNativeFileSystemType(filesystem_url.type());
141 void GetNonNativeLocalPathMimeType(
142 Profile* profile,
143 const base::FilePath& path,
144 const base::Callback<void(bool, const std::string&)>& callback) {
145 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
146 DCHECK(IsUnderNonNativeLocalPath(profile, path));
148 if (drive::util::IsUnderDriveMountPoint(path)) {
149 drive::FileSystemInterface* file_system =
150 drive::util::GetFileSystemByProfile(profile);
151 if (!file_system) {
152 content::BrowserThread::PostTask(
153 content::BrowserThread::UI,
154 FROM_HERE,
155 base::Bind(callback, false, std::string()));
156 return;
159 file_system->GetResourceEntry(
160 drive::util::ExtractDrivePath(path),
161 base::Bind(&GetMimeTypeAfterGetResourceEntryForDrive, callback));
162 return;
165 if (chromeos::file_system_provider::util::IsFileSystemProviderLocalPath(
166 path)) {
167 chromeos::file_system_provider::util::LocalPathParser parser(profile, path);
168 if (!parser.Parse()) {
169 content::BrowserThread::PostTask(
170 content::BrowserThread::UI,
171 FROM_HERE,
172 base::Bind(callback, false, std::string()));
173 return;
176 parser.file_system()->GetMetadata(
177 parser.file_path(),
178 chromeos::file_system_provider::ProvidedFileSystemInterface::
179 METADATA_FIELD_DEFAULT,
180 base::Bind(&GetMimeTypeAfterGetMetadataForProvidedFileSystem,
181 callback));
182 return;
185 // We don't have a way to obtain metadata other than drive and FSP. Returns an
186 // error with empty MIME type, that leads fallback guessing mime type from
187 // file extensions.
188 content::BrowserThread::PostTask(
189 content::BrowserThread::UI,
190 FROM_HERE,
191 base::Bind(callback, false /* failure */, std::string()));
194 void IsNonNativeLocalPathDirectory(
195 Profile* profile,
196 const base::FilePath& path,
197 const base::Callback<void(bool)>& callback) {
198 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
199 DCHECK(IsUnderNonNativeLocalPath(profile, path));
201 util::CheckIfDirectoryExists(
202 GetFileSystemContextForExtensionId(profile, kFileManagerAppId), path,
203 base::Bind(&BoolCallbackAsFileErrorCallback, callback));
206 void PrepareNonNativeLocalFileForWritableApp(
207 Profile* profile,
208 const base::FilePath& path,
209 const base::Callback<void(bool)>& callback) {
210 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
211 DCHECK(IsUnderNonNativeLocalPath(profile, path));
213 GURL url;
214 if (!util::ConvertAbsoluteFilePathToFileSystemUrl(
215 profile, path, kFileManagerAppId, &url)) {
216 // Posting to the current thread, so that we always call back asynchronously
217 // independent from whether or not the operation succeeds.
218 content::BrowserThread::PostTask(content::BrowserThread::UI,
219 FROM_HERE,
220 base::Bind(callback, false));
221 return;
224 scoped_refptr<storage::FileSystemContext> const file_system_context =
225 GetFileSystemContextForExtensionId(profile, kFileManagerAppId);
226 DCHECK(file_system_context);
227 storage::ExternalFileSystemBackend* const backend =
228 file_system_context->external_backend();
229 DCHECK(backend);
230 const storage::FileSystemURL internal_url =
231 backend->CreateInternalURL(file_system_context.get(), path);
233 content::BrowserThread::PostTask(
234 content::BrowserThread::IO, FROM_HERE,
235 base::Bind(&PrepareFileOnIOThread, file_system_context, internal_url,
236 google_apis::CreateRelayCallback(callback)));
239 } // namespace util
240 } // namespace file_manager