OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/gdata/gdata_file_system_proxy.h" | |
6 | |
7 #include <string> | |
8 #include <vector> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/platform_file.h" | |
12 #include "base/string_util.h" | |
13 #include "base/values.h" | |
14 #include "chrome/browser/chromeos/gdata/drive.pb.h" | |
15 #include "chrome/browser/chromeos/gdata/drive_files.h" | |
16 #include "chrome/browser/chromeos/gdata/gdata_file_system_interface.h" | |
17 #include "chrome/browser/chromeos/gdata/gdata_system_service.h" | |
18 #include "chrome/browser/chromeos/gdata/gdata_util.h" | |
19 #include "content/public/browser/browser_thread.h" | |
20 #include "webkit/blob/shareable_file_reference.h" | |
21 #include "webkit/fileapi/file_system_file_util_proxy.h" | |
22 #include "webkit/fileapi/file_system_types.h" | |
23 #include "webkit/fileapi/file_system_url.h" | |
24 #include "webkit/fileapi/file_system_util.h" | |
25 | |
26 using base::MessageLoopProxy; | |
27 using content::BrowserThread; | |
28 using fileapi::FileSystemURL; | |
29 using fileapi::FileSystemOperationInterface; | |
30 using webkit_blob::ShareableFileReference; | |
31 | |
32 namespace gdata { | |
33 | |
34 namespace { | |
35 | |
36 const char kDriveRootDirectory[] = "drive"; | |
37 const char kFeedField[] = "feed"; | |
38 | |
39 // Helper function that creates platform file on blocking IO thread pool. | |
40 void OpenPlatformFileOnIOPool(const FilePath& local_path, | |
41 int file_flags, | |
42 base::PlatformFile* platform_file, | |
43 base::PlatformFileError* open_error) { | |
44 bool created; | |
45 *platform_file = base::CreatePlatformFile(local_path, | |
46 file_flags, | |
47 &created, | |
48 open_error); | |
49 } | |
50 | |
51 // Helper function to run reply on results of OpenPlatformFileOnIOPool() on | |
52 // IO thread. | |
53 void OnPlatformFileOpened( | |
54 const FileSystemOperationInterface::OpenFileCallback& callback, | |
55 base::ProcessHandle peer_handle, | |
56 base::PlatformFile* platform_file, | |
57 base::PlatformFileError* open_error) { | |
58 callback.Run(*open_error, *platform_file, peer_handle); | |
59 } | |
60 | |
61 // Helper function to run OpenFileCallback from | |
62 // GDataFileSystemProxy::OpenFile(). | |
63 void OnGetFileByPathForOpen( | |
64 const FileSystemOperationInterface::OpenFileCallback& callback, | |
65 int file_flags, | |
66 base::ProcessHandle peer_handle, | |
67 DriveFileError file_error, | |
68 const FilePath& local_path, | |
69 const std::string& unused_mime_type, | |
70 DriveFileType file_type) { | |
71 base::PlatformFileError error = | |
72 util::DriveFileErrorToPlatformError(file_error); | |
73 if (error != base::PLATFORM_FILE_OK) { | |
74 callback.Run(error, base::kInvalidPlatformFileValue, peer_handle); | |
75 return; | |
76 } | |
77 | |
78 base::PlatformFile* platform_file = new base::PlatformFile( | |
79 base::kInvalidPlatformFileValue); | |
80 base::PlatformFileError* open_error = | |
81 new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED); | |
82 BrowserThread::GetBlockingPool()->PostTaskAndReply(FROM_HERE, | |
83 base::Bind(&OpenPlatformFileOnIOPool, | |
84 local_path, | |
85 file_flags, | |
86 platform_file, | |
87 open_error), | |
88 base::Bind(&OnPlatformFileOpened, | |
89 callback, | |
90 peer_handle, | |
91 base::Owned(platform_file), | |
92 base::Owned(open_error))); | |
93 } | |
94 | |
95 // Helper function to run SnapshotFileCallback from | |
96 // GDataFileSystemProxy::CreateSnapshotFile(). | |
97 void CallSnapshotFileCallback( | |
98 const FileSystemOperationInterface::SnapshotFileCallback& callback, | |
99 const base::PlatformFileInfo& file_info, | |
100 DriveFileError file_error, | |
101 const FilePath& local_path, | |
102 const std::string& unused_mime_type, | |
103 DriveFileType file_type) { | |
104 scoped_refptr<ShareableFileReference> file_ref; | |
105 base::PlatformFileError error = | |
106 util::DriveFileErrorToPlatformError(file_error); | |
107 | |
108 // If the file is a hosted document, a temporary JSON file is created to | |
109 // represent the document. The JSON file is not cached and its lifetime | |
110 // is managed by ShareableFileReference. | |
111 if (error == base::PLATFORM_FILE_OK && file_type == HOSTED_DOCUMENT) { | |
112 file_ref = ShareableFileReference::GetOrCreate( | |
113 local_path, ShareableFileReference::DELETE_ON_FINAL_RELEASE, | |
114 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); | |
115 } | |
116 | |
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::PlatformFileInfo final_file_info(file_info); | |
124 final_file_info.last_modified = base::Time(); | |
125 | |
126 callback.Run(error, final_file_info, local_path, file_ref); | |
127 } | |
128 | |
129 // Emits debug log when GDataFileSystem::CloseFile() is complete. | |
130 void EmitDebugLogForCloseFile(const FilePath& local_path, | |
131 DriveFileError error_code) { | |
132 DVLOG(1) << "Closed: " << local_path.AsUTF8Unsafe() << ": " << error_code; | |
133 } | |
134 | |
135 void DoTruncateOnFileThread( | |
136 const FilePath& local_cache_path, | |
137 int64 length, | |
138 base::PlatformFileError* result) { | |
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
140 | |
141 base::PlatformFile file = base::CreatePlatformFile( | |
142 local_cache_path, | |
143 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, | |
144 NULL, | |
145 result); | |
146 if (*result == base::PLATFORM_FILE_OK) { | |
147 DCHECK_NE(base::kInvalidPlatformFileValue, file); | |
148 if (!base::TruncatePlatformFile(file, length)) | |
149 *result = base::PLATFORM_FILE_ERROR_FAILED; | |
150 base::ClosePlatformFile(file); | |
151 } | |
152 } | |
153 | |
154 void DidCloseFileForTruncate( | |
155 const FileSystemOperationInterface::StatusCallback& callback, | |
156 base::PlatformFileError truncate_result, | |
157 DriveFileError close_result) { | |
158 // Reports the first error. | |
159 callback.Run(truncate_result == base::PLATFORM_FILE_OK ? | |
160 util::DriveFileErrorToPlatformError(close_result) : | |
161 truncate_result); | |
162 } | |
163 | |
164 } // namespace | |
165 | |
166 base::FileUtilProxy::Entry DriveEntryProtoToFileUtilProxyEntry( | |
167 const DriveEntryProto& proto) { | |
168 base::PlatformFileInfo file_info; | |
169 DriveEntry::ConvertProtoToPlatformFileInfo(proto.file_info(), &file_info); | |
170 | |
171 base::FileUtilProxy::Entry entry; | |
172 entry.name = proto.base_name(); | |
173 entry.is_directory = file_info.is_directory; | |
174 entry.size = file_info.size; | |
175 entry.last_modified_time = file_info.last_modified; | |
176 return entry; | |
177 } | |
178 | |
179 // GDataFileSystemProxy class implementation. | |
180 | |
181 GDataFileSystemProxy::GDataFileSystemProxy( | |
182 GDataFileSystemInterface* file_system) | |
183 : file_system_(file_system) { | |
184 // Should be created from the file browser extension API (AddMountFunction) | |
185 // on UI thread. | |
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
187 } | |
188 | |
189 void GDataFileSystemProxy::GetFileInfo(const FileSystemURL& file_url, | |
190 const FileSystemOperationInterface::GetMetadataCallback& callback) { | |
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
192 FilePath file_path; | |
193 if (!ValidateUrl(file_url, &file_path)) { | |
194 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
195 base::Bind(callback, | |
196 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
197 base::PlatformFileInfo(), | |
198 FilePath())); | |
199 return; | |
200 } | |
201 | |
202 file_system_->GetEntryInfoByPath( | |
203 file_path, | |
204 base::Bind(&GDataFileSystemProxy::OnGetMetadata, | |
205 this, | |
206 file_path, | |
207 callback)); | |
208 } | |
209 | |
210 void GDataFileSystemProxy::Copy(const FileSystemURL& src_file_url, | |
211 const FileSystemURL& dest_file_url, | |
212 const FileSystemOperationInterface::StatusCallback& callback) { | |
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
214 | |
215 FilePath src_file_path, dest_file_path; | |
216 if (!ValidateUrl(src_file_url, &src_file_path) || | |
217 !ValidateUrl(dest_file_url, &dest_file_path)) { | |
218 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
219 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
220 return; | |
221 } | |
222 | |
223 file_system_->Copy( | |
224 src_file_path, | |
225 dest_file_path, | |
226 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
227 } | |
228 | |
229 void GDataFileSystemProxy::Move(const FileSystemURL& src_file_url, | |
230 const FileSystemURL& dest_file_url, | |
231 const FileSystemOperationInterface::StatusCallback& callback) { | |
232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
233 | |
234 FilePath src_file_path, dest_file_path; | |
235 if (!ValidateUrl(src_file_url, &src_file_path) || | |
236 !ValidateUrl(dest_file_url, &dest_file_path)) { | |
237 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
238 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
239 return; | |
240 } | |
241 | |
242 file_system_->Move( | |
243 src_file_path, | |
244 dest_file_path, | |
245 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
246 } | |
247 | |
248 void GDataFileSystemProxy::ReadDirectory(const FileSystemURL& file_url, | |
249 const FileSystemOperationInterface::ReadDirectoryCallback& callback) { | |
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
251 | |
252 FilePath file_path; | |
253 if (!ValidateUrl(file_url, &file_path)) { | |
254 base::MessageLoopProxy::current()->PostTask( | |
255 FROM_HERE, | |
256 base::Bind(callback, | |
257 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
258 std::vector<base::FileUtilProxy::Entry>(), | |
259 false)); | |
260 return; | |
261 } | |
262 | |
263 file_system_->ReadDirectoryByPath( | |
264 file_path, | |
265 base::Bind(&GDataFileSystemProxy::OnReadDirectory, | |
266 this, | |
267 callback)); | |
268 } | |
269 | |
270 void GDataFileSystemProxy::Remove(const FileSystemURL& file_url, bool recursive, | |
271 const FileSystemOperationInterface::StatusCallback& callback) { | |
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
273 | |
274 FilePath file_path; | |
275 if (!ValidateUrl(file_url, &file_path)) { | |
276 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
277 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
278 return; | |
279 } | |
280 | |
281 file_system_->Remove( | |
282 file_path, | |
283 recursive, | |
284 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
285 } | |
286 | |
287 void GDataFileSystemProxy::CreateDirectory( | |
288 const FileSystemURL& file_url, | |
289 bool exclusive, | |
290 bool recursive, | |
291 const FileSystemOperationInterface::StatusCallback& callback) { | |
292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
293 | |
294 FilePath file_path; | |
295 if (!ValidateUrl(file_url, &file_path)) { | |
296 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
297 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
298 return; | |
299 } | |
300 | |
301 file_system_->CreateDirectory( | |
302 file_path, | |
303 exclusive, | |
304 recursive, | |
305 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
306 } | |
307 | |
308 void GDataFileSystemProxy::CreateFile( | |
309 const FileSystemURL& file_url, | |
310 bool exclusive, | |
311 const FileSystemOperationInterface::StatusCallback& callback) { | |
312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
313 | |
314 FilePath file_path; | |
315 if (!ValidateUrl(file_url, &file_path)) { | |
316 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
317 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
318 return; | |
319 } | |
320 | |
321 file_system_->CreateFile( | |
322 file_path, | |
323 exclusive, | |
324 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
325 } | |
326 | |
327 void GDataFileSystemProxy::Truncate( | |
328 const FileSystemURL& file_url, int64 length, | |
329 const FileSystemOperationInterface::StatusCallback& callback) { | |
330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
331 | |
332 if (length < 0) { | |
333 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
334 base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION)); | |
335 return; | |
336 } | |
337 | |
338 FilePath file_path; | |
339 if (!ValidateUrl(file_url, &file_path)) { | |
340 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
341 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
342 return; | |
343 } | |
344 | |
345 // TODO(kinaba): http://crbug.com/132780. | |
346 // Optimize the cases for small |length|, at least for |length| == 0. | |
347 // CreateWritableSnapshotFile downloads the whole content unnecessarily. | |
348 file_system_->OpenFile( | |
349 file_path, | |
350 base::Bind(&GDataFileSystemProxy::OnFileOpenedForTruncate, | |
351 this, | |
352 file_path, | |
353 length, | |
354 callback)); | |
355 } | |
356 | |
357 void GDataFileSystemProxy::OnOpenFileForWriting( | |
358 int file_flags, | |
359 base::ProcessHandle peer_handle, | |
360 const FileSystemOperationInterface::OpenFileCallback& callback, | |
361 DriveFileError file_error, | |
362 const FilePath& local_cache_path) { | |
363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
364 | |
365 base::PlatformFileError error = | |
366 util::DriveFileErrorToPlatformError(file_error); | |
367 | |
368 if (error != base::PLATFORM_FILE_OK) { | |
369 callback.Run(error, base::kInvalidPlatformFileValue, peer_handle); | |
370 return; | |
371 } | |
372 | |
373 // Cache file prepared for modification is available. Truncate it. | |
374 // File operation must be done on FILE thread, so relay the operation. | |
375 base::PlatformFileError* result = | |
376 new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED); | |
377 base::PlatformFile* platform_file = new base::PlatformFile( | |
378 base::kInvalidPlatformFileValue); | |
379 bool posted = BrowserThread::GetBlockingPool()->PostTaskAndReply(FROM_HERE, | |
380 base::Bind(&OpenPlatformFileOnIOPool, | |
381 local_cache_path, | |
382 file_flags, | |
383 platform_file, | |
384 result), | |
385 base::Bind(&OnPlatformFileOpened, | |
386 callback, | |
387 peer_handle, | |
388 base::Owned(platform_file), | |
389 base::Owned(result))); | |
390 DCHECK(posted); | |
391 } | |
392 | |
393 void GDataFileSystemProxy::OnCreateFileForOpen( | |
394 const FilePath& file_path, | |
395 int file_flags, | |
396 base::ProcessHandle peer_handle, | |
397 const FileSystemOperationInterface::OpenFileCallback& callback, | |
398 DriveFileError file_error) { | |
399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
400 base::PlatformFileError create_result = | |
401 util::DriveFileErrorToPlatformError(file_error); | |
402 | |
403 if ((create_result == base::PLATFORM_FILE_OK) || | |
404 ((create_result == base::PLATFORM_FILE_ERROR_EXISTS) && | |
405 (file_flags & base::PLATFORM_FILE_CREATE_ALWAYS))) { | |
406 // If we are trying to always create an existing file, then | |
407 // if it really exists open it as truncated. | |
408 file_flags &= ~base::PLATFORM_FILE_CREATE; | |
409 file_flags &= ~base::PLATFORM_FILE_CREATE_ALWAYS; | |
410 file_flags |= base::PLATFORM_FILE_OPEN_TRUNCATED; | |
411 } else { | |
412 callback.Run(create_result, base::kInvalidPlatformFileValue, peer_handle); | |
413 return; | |
414 } | |
415 | |
416 // Open created (or existing) file for writing. | |
417 file_system_->OpenFile( | |
418 file_path, | |
419 base::Bind(&GDataFileSystemProxy::OnOpenFileForWriting, | |
420 this, | |
421 file_flags, | |
422 peer_handle, | |
423 callback)); | |
424 } | |
425 | |
426 void GDataFileSystemProxy::OnFileOpenedForTruncate( | |
427 const FilePath& virtual_path, | |
428 int64 length, | |
429 const fileapi::FileSystemOperationInterface::StatusCallback& callback, | |
430 DriveFileError open_result, | |
431 const FilePath& local_cache_path) { | |
432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
433 | |
434 if (open_result != DRIVE_FILE_OK) { | |
435 callback.Run(util::DriveFileErrorToPlatformError(open_result)); | |
436 return; | |
437 } | |
438 | |
439 // Cache file prepared for modification is available. Truncate it. | |
440 // File operation must be done on FILE thread, so relay the operation. | |
441 base::PlatformFileError* result = | |
442 new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED); | |
443 bool posted = BrowserThread::GetMessageLoopProxyForThread( | |
444 BrowserThread::FILE)->PostTaskAndReply( | |
445 FROM_HERE, | |
446 base::Bind(&DoTruncateOnFileThread, | |
447 local_cache_path, | |
448 length, | |
449 result), | |
450 base::Bind(&GDataFileSystemProxy::DidTruncate, | |
451 this, | |
452 virtual_path, | |
453 callback, | |
454 base::Owned(result))); | |
455 DCHECK(posted); | |
456 } | |
457 | |
458 void GDataFileSystemProxy::DidTruncate( | |
459 const FilePath& virtual_path, | |
460 const FileSystemOperationInterface::StatusCallback& callback, | |
461 base::PlatformFileError* truncate_result) { | |
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
463 | |
464 // Truncation finished. We must close the file no matter |truncate_result| | |
465 // indicates an error or not. | |
466 file_system_->CloseFile( | |
467 virtual_path, | |
468 base::Bind(&DidCloseFileForTruncate, | |
469 callback, | |
470 base::PlatformFileError(*truncate_result))); | |
471 } | |
472 | |
473 void GDataFileSystemProxy::OpenFile( | |
474 const FileSystemURL& file_url, | |
475 int file_flags, | |
476 base::ProcessHandle peer_handle, | |
477 const FileSystemOperationInterface::OpenFileCallback& callback) { | |
478 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
479 | |
480 FilePath file_path; | |
481 if (!ValidateUrl(file_url, &file_path)) { | |
482 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
483 base::Bind(callback, | |
484 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
485 base::kInvalidPlatformFileValue, | |
486 peer_handle)); | |
487 return; | |
488 } | |
489 | |
490 // TODO(zelidrag): Wire all other file open operations. | |
491 if ((file_flags & base::PLATFORM_FILE_DELETE_ON_CLOSE)) { | |
492 NOTIMPLEMENTED() << "File create/write operations not yet supported " | |
493 << file_path.value(); | |
494 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
495 base::Bind(callback, | |
496 base::PLATFORM_FILE_ERROR_FAILED, | |
497 base::kInvalidPlatformFileValue, | |
498 peer_handle)); | |
499 return; | |
500 } | |
501 | |
502 if ((file_flags & base::PLATFORM_FILE_OPEN) || | |
503 (file_flags & base::PLATFORM_FILE_OPEN_ALWAYS) || | |
504 (file_flags & base::PLATFORM_FILE_OPEN_TRUNCATED)) { | |
505 if ((file_flags & base::PLATFORM_FILE_OPEN_TRUNCATED) || | |
506 (file_flags & base::PLATFORM_FILE_OPEN_ALWAYS) || | |
507 (file_flags & base::PLATFORM_FILE_WRITE) || | |
508 (file_flags & base::PLATFORM_FILE_EXCLUSIVE_WRITE)) { | |
509 // Open existing file for writing. | |
510 file_system_->OpenFile( | |
511 file_path, | |
512 base::Bind(&GDataFileSystemProxy::OnOpenFileForWriting, | |
513 this, | |
514 file_flags, | |
515 peer_handle, | |
516 callback)); | |
517 } else { | |
518 // Read-only file open. | |
519 file_system_->GetFileByPath(file_path, | |
520 base::Bind(&OnGetFileByPathForOpen, | |
521 callback, | |
522 file_flags, | |
523 peer_handle), | |
524 GetContentCallback()); | |
525 } | |
526 } else if ((file_flags & base::PLATFORM_FILE_CREATE) || | |
527 (file_flags & base::PLATFORM_FILE_CREATE_ALWAYS)) { | |
528 // Open existing file for writing. | |
529 file_system_->CreateFile( | |
530 file_path, | |
531 file_flags & base::PLATFORM_FILE_EXCLUSIVE_WRITE, | |
532 base::Bind(&GDataFileSystemProxy::OnCreateFileForOpen, | |
533 this, | |
534 file_path, | |
535 file_flags, | |
536 peer_handle, | |
537 callback)); | |
538 } else { | |
539 NOTREACHED() << "Unhandled file flags combination " << file_flags; | |
540 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
541 base::Bind(callback, | |
542 base::PLATFORM_FILE_ERROR_FAILED, | |
543 base::kInvalidPlatformFileValue, | |
544 peer_handle)); | |
545 } | |
546 } | |
547 | |
548 void GDataFileSystemProxy::NotifyCloseFile(const FileSystemURL& url) { | |
549 FilePath file_path; | |
550 if (!ValidateUrl(url, &file_path)) | |
551 return; | |
552 | |
553 file_system_->CloseFile(file_path, | |
554 base::Bind(&EmitDebugLogForCloseFile, file_path)); | |
555 } | |
556 | |
557 void GDataFileSystemProxy::CreateSnapshotFile( | |
558 const FileSystemURL& file_url, | |
559 const FileSystemOperationInterface::SnapshotFileCallback& callback) { | |
560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
561 | |
562 FilePath file_path; | |
563 if (!ValidateUrl(file_url, &file_path)) { | |
564 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
565 base::Bind(callback, | |
566 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
567 base::PlatformFileInfo(), | |
568 FilePath(), | |
569 scoped_refptr<ShareableFileReference>(NULL))); | |
570 return; | |
571 } | |
572 | |
573 file_system_->GetEntryInfoByPath( | |
574 file_path, | |
575 base::Bind(&GDataFileSystemProxy::OnGetEntryInfoByPath, | |
576 this, | |
577 file_path, | |
578 callback)); | |
579 } | |
580 | |
581 void GDataFileSystemProxy::OnGetEntryInfoByPath( | |
582 const FilePath& entry_path, | |
583 const FileSystemOperationInterface::SnapshotFileCallback& callback, | |
584 DriveFileError error, | |
585 scoped_ptr<DriveEntryProto> entry_proto) { | |
586 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
587 | |
588 if (error != DRIVE_FILE_OK || !entry_proto.get()) { | |
589 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
590 base::Bind(callback, | |
591 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
592 base::PlatformFileInfo(), | |
593 FilePath(), | |
594 scoped_refptr<ShareableFileReference>(NULL))); | |
595 return; | |
596 } | |
597 | |
598 base::PlatformFileInfo file_info; | |
599 DriveEntry::ConvertProtoToPlatformFileInfo( | |
600 entry_proto->file_info(), | |
601 &file_info); | |
602 | |
603 file_system_->GetFileByPath(entry_path, | |
604 base::Bind(&CallSnapshotFileCallback, | |
605 callback, | |
606 file_info), | |
607 GetContentCallback()); | |
608 } | |
609 | |
610 void GDataFileSystemProxy::CreateWritableSnapshotFile( | |
611 const FileSystemURL& file_url, | |
612 const fileapi::WritableSnapshotFile& callback) { | |
613 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
614 | |
615 FilePath file_path; | |
616 if (!ValidateUrl(file_url, &file_path)) { | |
617 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
618 base::Bind(callback, | |
619 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
620 FilePath(), | |
621 scoped_refptr<ShareableFileReference>(NULL))); | |
622 return; | |
623 } | |
624 | |
625 file_system_->OpenFile( | |
626 file_path, | |
627 base::Bind(&GDataFileSystemProxy::OnCreateWritableSnapshotFile, | |
628 this, | |
629 file_path, | |
630 callback)); | |
631 } | |
632 | |
633 GDataFileSystemProxy::~GDataFileSystemProxy() { | |
634 // Should be deleted from the CrosMountPointProvider on UI thread. | |
635 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
636 } | |
637 | |
638 // static. | |
639 bool GDataFileSystemProxy::ValidateUrl( | |
640 const FileSystemURL& url, FilePath* file_path) { | |
641 // what platform you're on. | |
642 if (!url.is_valid() || url.type() != fileapi::kFileSystemTypeDrive) { | |
643 return false; | |
644 } | |
645 *file_path = url.virtual_path(); | |
646 return true; | |
647 } | |
648 | |
649 void GDataFileSystemProxy::OnStatusCallback( | |
650 const fileapi::FileSystemOperationInterface::StatusCallback& callback, | |
651 DriveFileError error) { | |
652 callback.Run(util::DriveFileErrorToPlatformError(error)); | |
653 } | |
654 | |
655 void GDataFileSystemProxy::OnGetMetadata( | |
656 const FilePath& file_path, | |
657 const FileSystemOperationInterface::GetMetadataCallback& callback, | |
658 DriveFileError error, | |
659 scoped_ptr<DriveEntryProto> entry_proto) { | |
660 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
661 | |
662 if (error != DRIVE_FILE_OK) { | |
663 callback.Run(util::DriveFileErrorToPlatformError(error), | |
664 base::PlatformFileInfo(), | |
665 FilePath()); | |
666 return; | |
667 } | |
668 DCHECK(entry_proto.get()); | |
669 | |
670 base::PlatformFileInfo file_info; | |
671 DriveEntry::ConvertProtoToPlatformFileInfo( | |
672 entry_proto->file_info(), | |
673 &file_info); | |
674 | |
675 callback.Run(base::PLATFORM_FILE_OK, file_info, file_path); | |
676 } | |
677 | |
678 void GDataFileSystemProxy::OnReadDirectory( | |
679 const FileSystemOperationInterface::ReadDirectoryCallback& | |
680 callback, | |
681 DriveFileError error, | |
682 bool hide_hosted_documents, | |
683 scoped_ptr<DriveEntryProtoVector> proto_entries) { | |
684 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
685 | |
686 if (error != DRIVE_FILE_OK) { | |
687 callback.Run(util::DriveFileErrorToPlatformError(error), | |
688 std::vector<base::FileUtilProxy::Entry>(), | |
689 false); | |
690 return; | |
691 } | |
692 DCHECK(proto_entries.get()); | |
693 | |
694 std::vector<base::FileUtilProxy::Entry> entries; | |
695 // Convert gdata files to something File API stack can understand. | |
696 for (size_t i = 0; i < proto_entries->size(); ++i) { | |
697 const DriveEntryProto& proto = (*proto_entries)[i]; | |
698 if (proto.has_file_specific_info() && | |
699 proto.file_specific_info().is_hosted_document() && | |
700 hide_hosted_documents) { | |
701 continue; | |
702 } | |
703 entries.push_back(DriveEntryProtoToFileUtilProxyEntry(proto)); | |
704 } | |
705 | |
706 callback.Run(base::PLATFORM_FILE_OK, entries, false); | |
707 } | |
708 | |
709 void GDataFileSystemProxy::OnCreateWritableSnapshotFile( | |
710 const FilePath& virtual_path, | |
711 const fileapi::WritableSnapshotFile& callback, | |
712 DriveFileError result, | |
713 const FilePath& local_path) { | |
714 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
715 | |
716 scoped_refptr<ShareableFileReference> file_ref; | |
717 | |
718 if (result == DRIVE_FILE_OK) { | |
719 file_ref = ShareableFileReference::GetOrCreate( | |
720 local_path, | |
721 ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE, | |
722 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); | |
723 file_ref->AddFinalReleaseCallback( | |
724 base::Bind(&GDataFileSystemProxy::CloseWritableSnapshotFile, | |
725 this, | |
726 virtual_path)); | |
727 } | |
728 | |
729 callback.Run( | |
730 util::DriveFileErrorToPlatformError(result), local_path, file_ref); | |
731 } | |
732 | |
733 void GDataFileSystemProxy::CloseWritableSnapshotFile( | |
734 const FilePath& virtual_path, | |
735 const FilePath& local_path) { | |
736 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
737 | |
738 file_system_->CloseFile(virtual_path, | |
739 base::Bind(&EmitDebugLogForCloseFile, virtual_path)); | |
740 } | |
741 | |
742 } // namespace gdata | |
OLD | NEW |