Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_manager / filesystem_api_util.cc
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.
4
5 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
6
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_errors.h"
12 #include "chrome/browser/chromeos/drive/file_system_interface.h"
13 #include "chrome/browser/chromeos/drive/file_system_util.h"
14 #include "chrome/browser/chromeos/file_manager/app_id.h"
15 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
16 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
17 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
18 #include "chrome/browser/extensions/extension_util.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/storage_partition.h"
22 #include "google_apis/drive/task_util.h"
23 #include "storage/browser/fileapi/file_system_context.h"
24
25 namespace file_manager {
26 namespace util {
27 namespace {
28
29 // Helper function used to implement GetNonNativeLocalPathMimeType. It extracts
30 // the mime type from the passed Drive resource entry.
31 void GetMimeTypeAfterGetResourceEntryForDrive(
32     const base::Callback<void(bool, const std::string&)>& callback,
33     drive::FileError error,
34     scoped_ptr<drive::ResourceEntry> entry) {
35   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
36
37   if (error != drive::FILE_ERROR_OK || !entry->has_file_specific_info() ||
38       entry->file_specific_info().content_mime_type().empty()) {
39     callback.Run(false, std::string());
40     return;
41   }
42   callback.Run(true, entry->file_specific_info().content_mime_type());
43 }
44
45 // Helper function used to implement GetNonNativeLocalPathMimeType. It extracts
46 // the mime type from the passed metadata from a providing extension.
47 void GetMimeTypeAfterGetMetadataForProvidedFileSystem(
48     const base::Callback<void(bool, const std::string&)>& callback,
49     scoped_ptr<chromeos::file_system_provider::EntryMetadata> metadata,
50     base::File::Error result) {
51   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
52
53   if (result != base::File::FILE_OK || metadata->mime_type.empty()) {
54     callback.Run(false, std::string());
55     return;
56   }
57   callback.Run(true, metadata->mime_type);
58 }
59
60 // Helper function to converts a callback that takes boolean value to that takes
61 // File::Error, by regarding FILE_OK as the only successful value.
62 void BoolCallbackAsFileErrorCallback(
63     const base::Callback<void(bool)>& callback,
64     base::File::Error error) {
65   return callback.Run(error == base::File::FILE_OK);
66 }
67
68 // Part of PrepareFileOnIOThread. It tries to create a new file if the given
69 // |url| is not already inhabited.
70 void PrepareFileAfterCheckExistOnIOThread(
71     scoped_refptr<storage::FileSystemContext> file_system_context,
72     const storage::FileSystemURL& url,
73     const storage::FileSystemOperation::StatusCallback& callback,
74     base::File::Error error) {
75   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
76
77   if (error != base::File::FILE_ERROR_NOT_FOUND) {
78     callback.Run(error);
79     return;
80   }
81
82   // Call with the second argument |exclusive| set to false, meaning that it
83   // is not an error even if the file already exists (it can happen if the file
84   // is created after the previous FileExists call and before this CreateFile.)
85   //
86   // Note that the preceding call to FileExists is necessary for handling
87   // read only filesystems that blindly rejects handling CreateFile().
88   file_system_context->operation_runner()->CreateFile(url, false, callback);
89 }
90
91 // Checks whether a file exists at the given |url|, and try creating it if it
92 // is not already there.
93 void PrepareFileOnIOThread(
94     scoped_refptr<storage::FileSystemContext> file_system_context,
95     const storage::FileSystemURL& url,
96     const base::Callback<void(bool)>& callback) {
97   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
98
99   file_system_context->operation_runner()->FileExists(
100       url,
101       base::Bind(&PrepareFileAfterCheckExistOnIOThread,
102                  file_system_context,
103                  url,
104                  base::Bind(&BoolCallbackAsFileErrorCallback, callback)));
105 }
106
107 }  // namespace
108
109 bool IsNonNativeFileSystemType(storage::FileSystemType type) {
110   switch (type) {
111     case storage::kFileSystemTypeNativeLocal:
112     case storage::kFileSystemTypeRestrictedNativeLocal:
113       return false;
114     default:
115       // The path indeed corresponds to a mount point not associated with a
116       // native local path.
117       return true;
118   }
119 }
120
121 bool IsUnderNonNativeLocalPath(Profile* profile,
122                         const base::FilePath& path) {
123   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
124
125   GURL url;
126   if (!util::ConvertAbsoluteFilePathToFileSystemUrl(
127            profile, path, kFileManagerAppId, &url)) {
128     return false;
129   }
130
131   storage::FileSystemURL filesystem_url =
132       GetFileSystemContextForExtensionId(profile, kFileManagerAppId)
133           ->CrackURL(url);
134   if (!filesystem_url.is_valid())
135     return false;
136
137   return IsNonNativeFileSystemType(filesystem_url.type());
138 }
139
140 void GetNonNativeLocalPathMimeType(
141     Profile* profile,
142     const base::FilePath& path,
143     const base::Callback<void(bool, const std::string&)>& callback) {
144   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
145   DCHECK(IsUnderNonNativeLocalPath(profile, path));
146
147   if (drive::util::IsUnderDriveMountPoint(path)) {
148     drive::FileSystemInterface* file_system =
149         drive::util::GetFileSystemByProfile(profile);
150     if (!file_system) {
151       content::BrowserThread::PostTask(
152           content::BrowserThread::UI,
153           FROM_HERE,
154           base::Bind(callback, false, std::string()));
155       return;
156     }
157
158     file_system->GetResourceEntry(
159         drive::util::ExtractDrivePath(path),
160         base::Bind(&GetMimeTypeAfterGetResourceEntryForDrive, callback));
161     return;
162   }
163
164   if (chromeos::file_system_provider::util::IsFileSystemProviderLocalPath(
165           path)) {
166     chromeos::file_system_provider::util::LocalPathParser parser(profile, path);
167     if (!parser.Parse()) {
168       content::BrowserThread::PostTask(
169           content::BrowserThread::UI,
170           FROM_HERE,
171           base::Bind(callback, false, std::string()));
172       return;
173     }
174
175     parser.file_system()->GetMetadata(
176         parser.file_path(),
177         chromeos::file_system_provider::ProvidedFileSystemInterface::
178             METADATA_FIELD_DEFAULT,
179         base::Bind(&GetMimeTypeAfterGetMetadataForProvidedFileSystem,
180                    callback));
181     return;
182   }
183
184   // We don't have a way to obtain metadata other than drive and FSP. Returns an
185   // error with empty MIME type, that leads fallback guessing mime type from
186   // file extensions.
187   content::BrowserThread::PostTask(
188       content::BrowserThread::UI,
189       FROM_HERE,
190       base::Bind(callback, false /* failure */, std::string()));
191 }
192
193 void IsNonNativeLocalPathDirectory(
194     Profile* profile,
195     const base::FilePath& path,
196     const base::Callback<void(bool)>& callback) {
197   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
198   DCHECK(IsUnderNonNativeLocalPath(profile, path));
199
200   GURL url;
201   if (!util::ConvertAbsoluteFilePathToFileSystemUrl(
202            profile, path, kFileManagerAppId, &url)) {
203     // Posting to the current thread, so that we always call back asynchronously
204     // independent from whether or not the operation succeeds.
205     content::BrowserThread::PostTask(content::BrowserThread::UI,
206                                      FROM_HERE,
207                                      base::Bind(callback, false));
208     return;
209   }
210
211   util::CheckIfDirectoryExists(
212       GetFileSystemContextForExtensionId(profile, kFileManagerAppId),
213       url,
214       base::Bind(&BoolCallbackAsFileErrorCallback, callback));
215 }
216
217 void PrepareNonNativeLocalFileForWritableApp(
218     Profile* profile,
219     const base::FilePath& path,
220     const base::Callback<void(bool)>& callback) {
221   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
222   DCHECK(IsUnderNonNativeLocalPath(profile, path));
223
224   GURL url;
225   if (!util::ConvertAbsoluteFilePathToFileSystemUrl(
226            profile, path, kFileManagerAppId, &url)) {
227     // Posting to the current thread, so that we always call back asynchronously
228     // independent from whether or not the operation succeeds.
229     content::BrowserThread::PostTask(content::BrowserThread::UI,
230                                      FROM_HERE,
231                                      base::Bind(callback, false));
232     return;
233   }
234
235   storage::FileSystemContext* const context =
236       GetFileSystemContextForExtensionId(profile, kFileManagerAppId);
237   DCHECK(context);
238
239   // Check the existence of a file using file system API implementation on
240   // behalf of the file manager app. We need to grant access beforehand.
241   context->external_backend()->GrantFullAccessToExtension(kFileManagerAppId);
242
243   content::BrowserThread::PostTask(
244       content::BrowserThread::IO,
245       FROM_HERE,
246       base::Bind(&PrepareFileOnIOThread,
247                  make_scoped_refptr(context),
248                  context->CrackURL(url),
249                  google_apis::CreateRelayCallback(callback)));
250 }
251
252 }  // namespace util
253 }  // namespace file_manager