Update broken references to image assets
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / fileapi / fileapi_worker.cc
blob0d8b2322c5d81cc8f513175aa32f9464cf212f0c
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/drive/fileapi/fileapi_worker.h"
7 #include "base/files/file_path.h"
8 #include "base/logging.h"
9 #include "base/task_runner_util.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "chrome/browser/chromeos/drive/file_system_interface.h"
13 #include "chrome/browser/chromeos/drive/file_system_util.h"
14 #include "components/drive/drive.pb.h"
15 #include "components/drive/file_errors.h"
16 #include "components/drive/resource_entry_conversion.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "storage/browser/fileapi/file_system_url.h"
19 #include "storage/common/fileapi/directory_entry.h"
21 using content::BrowserThread;
23 namespace drive {
24 namespace fileapi_internal {
25 namespace {
27 // The summary of opening mode is:
28 // - File::FLAG_OPEN: Open the existing file. Fail if not exists.
29 // - File::FLAG_CREATE: Create the file if not exists. Fail if exists.
30 // - File::FLAG_OPEN_ALWAYS: Open the existing file. Create a new file
31 // if not exists.
32 // - File::FLAG_CREATE_ALWAYS: Create a new file if not exists. If exists
33 // open it with truncate.
34 // - File::FLAG_OPEN_TRUNCATE: Open the existing file with truncate.
35 // Fail if not exists.
36 OpenMode GetOpenMode(int file_flag) {
37 if (file_flag & (base::File::FLAG_OPEN | base::File::FLAG_OPEN_TRUNCATED))
38 return OPEN_FILE;
40 if (file_flag & base::File::FLAG_CREATE)
41 return CREATE_FILE;
43 DCHECK(file_flag &
44 (base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_CREATE_ALWAYS));
45 return OPEN_OR_CREATE_FILE;
48 // Runs |callback| with the File::Error converted from |error|.
49 void RunStatusCallbackByFileError(const StatusCallback& callback,
50 FileError error) {
51 callback.Run(FileErrorToBaseFileError(error));
54 // Runs |callback| with arguments converted from |error| and |entry|.
55 void RunGetFileInfoCallback(const GetFileInfoCallback& callback,
56 FileError error,
57 scoped_ptr<ResourceEntry> entry) {
58 if (error != FILE_ERROR_OK) {
59 callback.Run(FileErrorToBaseFileError(error), base::File::Info());
60 return;
63 DCHECK(entry);
64 base::File::Info file_info;
65 ConvertResourceEntryToFileInfo(*entry, &file_info);
66 callback.Run(base::File::FILE_OK, file_info);
69 // Runs |callback| with entries.
70 void RunReadDirectoryCallbackWithEntries(
71 const ReadDirectoryCallback& callback,
72 scoped_ptr<ResourceEntryVector> resource_entries) {
73 DCHECK(resource_entries);
75 std::vector<storage::DirectoryEntry> entries;
76 // Convert drive files to File API's directory entry.
77 entries.reserve(resource_entries->size());
78 for (size_t i = 0; i < resource_entries->size(); ++i) {
79 const ResourceEntry& resource_entry = (*resource_entries)[i];
80 storage::DirectoryEntry entry;
81 entry.name = resource_entry.base_name();
83 const PlatformFileInfoProto& file_info = resource_entry.file_info();
84 entry.is_directory = file_info.is_directory();
85 entry.size = file_info.size();
86 entry.last_modified_time =
87 base::Time::FromInternalValue(file_info.last_modified());
88 entries.push_back(entry);
91 callback.Run(base::File::FILE_OK, entries, true /*has_more*/);
94 // Runs |callback| with |error|.
95 void RunReadDirectoryCallbackOnCompletion(const ReadDirectoryCallback& callback,
96 FileError error) {
97 callback.Run(FileErrorToBaseFileError(error),
98 std::vector<storage::DirectoryEntry>(),
99 false /*has_more*/);
102 // Runs |callback| with arguments based on |error|, |local_path| and |entry|.
103 void RunCreateSnapshotFileCallback(const CreateSnapshotFileCallback& callback,
104 FileError error,
105 const base::FilePath& local_path,
106 scoped_ptr<ResourceEntry> entry) {
107 if (error != FILE_ERROR_OK) {
108 callback.Run(FileErrorToBaseFileError(error),
109 base::File::Info(),
110 base::FilePath(),
111 storage::ScopedFile::ScopeOutPolicy());
112 return;
115 DCHECK(entry);
117 // When reading file, last modified time specified in file info will be
118 // compared to the last modified time of the local version of the drive file.
119 // Since those two values don't generally match (last modification time on the
120 // drive server vs. last modification time of the local, downloaded file), so
121 // we have to opt out from this check. We do this by unsetting last_modified
122 // value in the file info passed to the CreateSnapshot caller.
123 base::File::Info file_info;
124 ConvertResourceEntryToFileInfo(*entry, &file_info);
125 file_info.last_modified = base::Time();
127 // If the file is a hosted document, a temporary JSON file is created to
128 // represent the document. The JSON file is not cached and its lifetime
129 // is managed by ShareableFileReference.
130 storage::ScopedFile::ScopeOutPolicy scope_out_policy =
131 entry->file_specific_info().is_hosted_document()
132 ? storage::ScopedFile::DELETE_ON_SCOPE_OUT
133 : storage::ScopedFile::DONT_DELETE_ON_SCOPE_OUT;
135 callback.Run(base::File::FILE_OK, file_info, local_path, scope_out_policy);
138 // Runs |callback| with arguments converted from |error| and |local_path|.
139 void RunCreateWritableSnapshotFileCallback(
140 const CreateWritableSnapshotFileCallback& callback,
141 FileError error,
142 const base::FilePath& local_path,
143 const base::Closure& close_callback) {
144 DCHECK_CURRENTLY_ON(BrowserThread::UI);
145 callback.Run(FileErrorToBaseFileError(error), local_path, close_callback);
148 // Runs |callback| with |file|.
149 void RunOpenFileCallback(const OpenFileCallback& callback,
150 const base::Closure& close_callback,
151 base::File file) {
152 callback.Run(file.Pass(), close_callback);
155 base::File OpenFile(const base::FilePath& path, int flags) {
156 return base::File(path, flags);
159 // Part of OpenFile(). Called after FileSystem::OpenFile().
160 void OpenFileAfterFileSystemOpenFile(int file_flags,
161 const OpenFileCallback& callback,
162 FileError error,
163 const base::FilePath& local_path,
164 const base::Closure& close_callback) {
165 DCHECK_CURRENTLY_ON(BrowserThread::UI);
167 if (error != FILE_ERROR_OK) {
168 callback.Run(base::File(FileErrorToBaseFileError(error)), base::Closure());
169 return;
172 // Here, the file should be at |local_path|, but there may be timing issue.
173 // Because the file is managed by Drive file system, so, in order to avoid
174 // unexpected file creation, CREATE, OPEN_ALWAYS and CREATE_ALWAYS are
175 // translated into OPEN or OPEN_TRUNCATED, here. Keep OPEN and OPEN_TRUNCATED
176 // as is.
177 if (file_flags & (base::File::FLAG_CREATE |
178 base::File::FLAG_OPEN_ALWAYS)) {
179 file_flags &= ~(base::File::FLAG_CREATE |
180 base::File::FLAG_OPEN_ALWAYS);
181 file_flags |= base::File::FLAG_OPEN;
182 } else if (file_flags & base::File::FLAG_CREATE_ALWAYS) {
183 file_flags &= ~base::File::FLAG_CREATE_ALWAYS;
184 file_flags |= base::File::FLAG_OPEN_TRUNCATED;
187 // Cache file prepared for modification is available. Open it locally.
188 bool posted = base::PostTaskAndReplyWithResult(
189 BrowserThread::GetBlockingPool(), FROM_HERE,
190 base::Bind(&OpenFile, local_path, file_flags),
191 base::Bind(&RunOpenFileCallback, callback, close_callback));
192 DCHECK(posted);
195 } // namespace
197 FileSystemInterface* GetFileSystemFromUrl(const storage::FileSystemURL& url) {
198 DCHECK_CURRENTLY_ON(BrowserThread::UI);
200 Profile* profile = util::ExtractProfileFromPath(url.path());
201 return profile ? util::GetFileSystemByProfile(profile) : NULL;
204 void RunFileSystemCallback(
205 const FileSystemGetter& file_system_getter,
206 const base::Callback<void(FileSystemInterface*)>& callback,
207 const base::Closure& on_error_callback) {
208 DCHECK_CURRENTLY_ON(BrowserThread::UI);
209 FileSystemInterface* file_system = file_system_getter.Run();
211 if (!file_system) {
212 if (!on_error_callback.is_null())
213 on_error_callback.Run();
214 return;
217 callback.Run(file_system);
220 void GetFileInfo(const base::FilePath& file_path,
221 const GetFileInfoCallback& callback,
222 FileSystemInterface* file_system) {
223 DCHECK_CURRENTLY_ON(BrowserThread::UI);
224 file_system->GetResourceEntry(
225 file_path,
226 base::Bind(&RunGetFileInfoCallback, callback));
229 void Copy(const base::FilePath& src_file_path,
230 const base::FilePath& dest_file_path,
231 bool preserve_last_modified,
232 const StatusCallback& callback,
233 FileSystemInterface* file_system) {
234 DCHECK_CURRENTLY_ON(BrowserThread::UI);
235 file_system->Copy(src_file_path, dest_file_path, preserve_last_modified,
236 base::Bind(&RunStatusCallbackByFileError, callback));
239 void Move(const base::FilePath& src_file_path,
240 const base::FilePath& dest_file_path,
241 const StatusCallback& callback,
242 FileSystemInterface* file_system) {
243 DCHECK_CURRENTLY_ON(BrowserThread::UI);
244 file_system->Move(src_file_path, dest_file_path,
245 base::Bind(&RunStatusCallbackByFileError, callback));
248 void CopyInForeignFile(const base::FilePath& src_foreign_file_path,
249 const base::FilePath& dest_file_path,
250 const StatusCallback& callback,
251 FileSystemInterface* file_system) {
252 DCHECK_CURRENTLY_ON(BrowserThread::UI);
253 file_system->TransferFileFromLocalToRemote(
254 src_foreign_file_path, dest_file_path,
255 base::Bind(&RunStatusCallbackByFileError, callback));
258 void ReadDirectory(const base::FilePath& file_path,
259 const ReadDirectoryCallback& callback,
260 FileSystemInterface* file_system) {
261 DCHECK_CURRENTLY_ON(BrowserThread::UI);
262 file_system->ReadDirectory(
263 file_path,
264 base::Bind(&RunReadDirectoryCallbackWithEntries, callback),
265 base::Bind(&RunReadDirectoryCallbackOnCompletion, callback));
268 void Remove(const base::FilePath& file_path,
269 bool is_recursive,
270 const StatusCallback& callback,
271 FileSystemInterface* file_system) {
272 DCHECK_CURRENTLY_ON(BrowserThread::UI);
273 file_system->Remove(file_path, is_recursive,
274 base::Bind(&RunStatusCallbackByFileError, callback));
277 void CreateDirectory(const base::FilePath& file_path,
278 bool is_exclusive,
279 bool is_recursive,
280 const StatusCallback& callback,
281 FileSystemInterface* file_system) {
282 DCHECK_CURRENTLY_ON(BrowserThread::UI);
283 file_system->CreateDirectory(
284 file_path, is_exclusive, is_recursive,
285 base::Bind(&RunStatusCallbackByFileError, callback));
288 void CreateFile(const base::FilePath& file_path,
289 bool is_exclusive,
290 const StatusCallback& callback,
291 FileSystemInterface* file_system) {
292 DCHECK_CURRENTLY_ON(BrowserThread::UI);
293 file_system->CreateFile(file_path, is_exclusive,
294 std::string(), // no mime type; guess from file_path
295 base::Bind(&RunStatusCallbackByFileError, callback));
298 void Truncate(const base::FilePath& file_path,
299 int64 length,
300 const StatusCallback& callback,
301 FileSystemInterface* file_system) {
302 DCHECK_CURRENTLY_ON(BrowserThread::UI);
303 file_system->TruncateFile(
304 file_path, length,
305 base::Bind(&RunStatusCallbackByFileError, callback));
308 void CreateSnapshotFile(const base::FilePath& file_path,
309 const CreateSnapshotFileCallback& callback,
310 FileSystemInterface* file_system) {
311 DCHECK_CURRENTLY_ON(BrowserThread::UI);
312 file_system->GetFile(file_path,
313 base::Bind(&RunCreateSnapshotFileCallback, callback));
316 void CreateWritableSnapshotFile(
317 const base::FilePath& file_path,
318 const CreateWritableSnapshotFileCallback& callback,
319 FileSystemInterface* file_system) {
320 DCHECK_CURRENTLY_ON(BrowserThread::UI);
321 file_system->OpenFile(
322 file_path,
323 OPEN_FILE,
324 std::string(), // no mime type; we never create a new file here.
325 base::Bind(&RunCreateWritableSnapshotFileCallback, callback));
328 void OpenFile(const base::FilePath& file_path,
329 int file_flags,
330 const OpenFileCallback& callback,
331 FileSystemInterface* file_system) {
332 DCHECK_CURRENTLY_ON(BrowserThread::UI);
334 // Returns an error if any unsupported flag is found.
335 if (file_flags & ~(base::File::FLAG_OPEN |
336 base::File::FLAG_CREATE |
337 base::File::FLAG_OPEN_ALWAYS |
338 base::File::FLAG_CREATE_ALWAYS |
339 base::File::FLAG_OPEN_TRUNCATED |
340 base::File::FLAG_READ |
341 base::File::FLAG_WRITE |
342 base::File::FLAG_WRITE_ATTRIBUTES |
343 base::File::FLAG_APPEND)) {
344 base::ThreadTaskRunnerHandle::Get()->PostTask(
345 FROM_HERE,
346 base::Bind(callback,
347 Passed(base::File(base::File::FILE_ERROR_FAILED)),
348 base::Closure()));
349 return;
352 file_system->OpenFile(
353 file_path, GetOpenMode(file_flags),
354 std::string(), // no mime type; guess from file_path
355 base::Bind(&OpenFileAfterFileSystemOpenFile, file_flags, callback));
358 void TouchFile(const base::FilePath& file_path,
359 const base::Time& last_access_time,
360 const base::Time& last_modified_time,
361 const StatusCallback& callback,
362 FileSystemInterface* file_system) {
363 DCHECK_CURRENTLY_ON(BrowserThread::UI);
364 file_system->TouchFile(file_path, last_access_time, last_modified_time,
365 base::Bind(&RunStatusCallbackByFileError, callback));
369 } // namespace fileapi_internal
370 } // namespace drive