Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / drive / file_system.cc
blob78670b3a692faae0ce9b5791574ac4909ce29ef4
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.
5 #include "components/drive/file_system.h"
7 #include "base/bind.h"
8 #include "base/files/file_util.h"
9 #include "base/prefs/pref_service.h"
10 #include "components/drive/change_list_loader.h"
11 #include "components/drive/directory_loader.h"
12 #include "components/drive/drive.pb.h"
13 #include "components/drive/drive_pref_names.h"
14 #include "components/drive/file_cache.h"
15 #include "components/drive/file_change.h"
16 #include "components/drive/file_system/copy_operation.h"
17 #include "components/drive/file_system/create_directory_operation.h"
18 #include "components/drive/file_system/create_file_operation.h"
19 #include "components/drive/file_system/download_operation.h"
20 #include "components/drive/file_system/get_file_for_saving_operation.h"
21 #include "components/drive/file_system/move_operation.h"
22 #include "components/drive/file_system/open_file_operation.h"
23 #include "components/drive/file_system/remove_operation.h"
24 #include "components/drive/file_system/search_operation.h"
25 #include "components/drive/file_system/set_property_operation.h"
26 #include "components/drive/file_system/touch_operation.h"
27 #include "components/drive/file_system/truncate_operation.h"
28 #include "components/drive/file_system_core_util.h"
29 #include "components/drive/file_system_observer.h"
30 #include "components/drive/job_scheduler.h"
31 #include "components/drive/remove_stale_cache_files.h"
32 #include "components/drive/resource_entry_conversion.h"
33 #include "components/drive/search_metadata.h"
34 #include "components/drive/sync_client.h"
35 #include "google_apis/drive/drive_api_parser.h"
37 namespace drive {
38 namespace {
40 // Gets a ResourceEntry from the metadata, and overwrites its file info when the
41 // cached file is dirty.
42 FileError GetLocallyStoredResourceEntry(
43 internal::ResourceMetadata* resource_metadata,
44 internal::FileCache* cache,
45 const base::FilePath& file_path,
46 ResourceEntry* entry) {
47 std::string local_id;
48 FileError error = resource_metadata->GetIdByPath(file_path, &local_id);
49 if (error != FILE_ERROR_OK)
50 return error;
52 error = resource_metadata->GetResourceEntryById(local_id, entry);
53 if (error != FILE_ERROR_OK)
54 return error;
56 // For entries that will never be cached, use the original resource entry
57 // as is.
58 if (!entry->has_file_specific_info() ||
59 entry->file_specific_info().is_hosted_document())
60 return FILE_ERROR_OK;
62 // When cache is not found, use the original resource entry as is.
63 if (!entry->file_specific_info().has_cache_state())
64 return FILE_ERROR_OK;
66 // When cache is non-dirty and obsolete (old hash), use the original entry.
67 if (!entry->file_specific_info().cache_state().is_dirty() &&
68 entry->file_specific_info().md5() !=
69 entry->file_specific_info().cache_state().md5())
70 return FILE_ERROR_OK;
72 // If there's a valid cache, obtain the file info from the cache file itself.
73 base::FilePath local_cache_path;
74 error = cache->GetFile(local_id, &local_cache_path);
75 if (error != FILE_ERROR_OK)
76 return error;
78 base::File::Info file_info;
79 if (!base::GetFileInfo(local_cache_path, &file_info))
80 return FILE_ERROR_NOT_FOUND;
82 entry->mutable_file_info()->set_size(file_info.size);
83 return FILE_ERROR_OK;
86 // Runs the callback with parameters.
87 void RunGetResourceEntryCallback(const GetResourceEntryCallback& callback,
88 scoped_ptr<ResourceEntry> entry,
89 FileError error) {
90 DCHECK(!callback.is_null());
92 if (error != FILE_ERROR_OK)
93 entry.reset();
94 callback.Run(error, entry.Pass());
97 // Used to implement Pin().
98 FileError PinInternal(internal::ResourceMetadata* resource_metadata,
99 internal::FileCache* cache,
100 const base::FilePath& file_path,
101 std::string* local_id) {
102 FileError error = resource_metadata->GetIdByPath(file_path, local_id);
103 if (error != FILE_ERROR_OK)
104 return error;
106 ResourceEntry entry;
107 error = resource_metadata->GetResourceEntryById(*local_id, &entry);
108 if (error != FILE_ERROR_OK)
109 return error;
111 // TODO(hashimoto): Support pinning directories. crbug.com/127831
112 if (entry.file_info().is_directory())
113 return FILE_ERROR_NOT_A_FILE;
115 return cache->Pin(*local_id);
118 // Used to implement Unpin().
119 FileError UnpinInternal(internal::ResourceMetadata* resource_metadata,
120 internal::FileCache* cache,
121 const base::FilePath& file_path,
122 std::string* local_id) {
123 FileError error = resource_metadata->GetIdByPath(file_path, local_id);
124 if (error != FILE_ERROR_OK)
125 return error;
127 return cache->Unpin(*local_id);
130 // Used to implement MarkCacheFileAsMounted().
131 FileError MarkCacheFileAsMountedInternal(
132 internal::ResourceMetadata* resource_metadata,
133 internal::FileCache* cache,
134 const base::FilePath& drive_file_path,
135 base::FilePath* cache_file_path) {
136 std::string local_id;
137 FileError error = resource_metadata->GetIdByPath(drive_file_path, &local_id);
138 if (error != FILE_ERROR_OK)
139 return error;
141 return cache->MarkAsMounted(local_id, cache_file_path);
144 // Runs the callback with arguments.
145 void RunMarkMountedCallback(const MarkMountedCallback& callback,
146 base::FilePath* cache_file_path,
147 FileError error) {
148 DCHECK(!callback.is_null());
149 callback.Run(error, *cache_file_path);
152 // Callback for ResourceMetadata::GetLargestChangestamp.
153 // |callback| must not be null.
154 void OnGetLargestChangestamp(
155 FileSystemMetadata metadata, // Will be modified.
156 const GetFilesystemMetadataCallback& callback,
157 const int64* largest_changestamp,
158 FileError error) {
159 DCHECK(!callback.is_null());
161 metadata.largest_changestamp = *largest_changestamp;
162 callback.Run(metadata);
165 // Thin adapter to map GetFileCallback to FileOperationCallback.
166 void GetFileCallbackToFileOperationCallbackAdapter(
167 const FileOperationCallback& callback,
168 FileError error,
169 const base::FilePath& unused_file_path,
170 scoped_ptr<ResourceEntry> unused_entry) {
171 callback.Run(error);
174 // Clears |resource_metadata| and |cache|.
175 FileError ResetOnBlockingPool(internal::ResourceMetadata* resource_metadata,
176 internal::FileCache* cache) {
177 FileError error = resource_metadata->Reset();
178 if (error != FILE_ERROR_OK)
179 return error;
180 return cache->ClearAll() ? FILE_ERROR_OK : FILE_ERROR_FAILED;
183 // Part of GetPathFromResourceId().
184 // Obtains |file_path| from |resource_id|. The function should be run on the
185 // blocking pool.
186 FileError GetPathFromResourceIdOnBlockingPool(
187 internal::ResourceMetadata* resource_metadata,
188 const std::string& resource_id,
189 base::FilePath* file_path) {
190 std::string local_id;
191 const FileError error =
192 resource_metadata->GetIdByResourceId(resource_id, &local_id);
193 if (error != FILE_ERROR_OK)
194 return error;
195 return resource_metadata->GetFilePath(local_id, file_path);
198 // Part of GetPathFromResourceId().
199 // Called when GetPathFromResourceIdInBlockingPool is complete.
200 void GetPathFromResourceIdAfterGetPath(base::FilePath* file_path,
201 const GetFilePathCallback& callback,
202 FileError error) {
203 callback.Run(error, *file_path);
206 bool FreeDiskSpaceIfNeededForOnBlockingPool(internal::FileCache* cache,
207 int64 num_bytes) {
208 return cache->FreeDiskSpaceIfNeededFor(num_bytes);
211 uint64_t CalculateEvictableCacheSizeOnBlockingPool(internal::FileCache* cache) {
212 return cache->CalculateEvictableCacheSize();
215 // Excludes hosted documents from the given entries.
216 // Used to implement ReadDirectory().
217 void FilterHostedDocuments(const ReadDirectoryEntriesCallback& callback,
218 scoped_ptr<ResourceEntryVector> entries) {
219 DCHECK(!callback.is_null());
221 if (entries) {
222 // TODO(kinaba): Stop handling hide_hosted_docs here. crbug.com/256520.
223 scoped_ptr<ResourceEntryVector> filtered(new ResourceEntryVector);
224 for (size_t i = 0; i < entries->size(); ++i) {
225 if (entries->at(i).file_specific_info().is_hosted_document()) {
226 continue;
228 filtered->push_back(entries->at(i));
230 entries.swap(filtered);
232 callback.Run(entries.Pass());
235 // Adapter for using FileOperationCallback as google_apis::EntryActionCallback.
236 void RunFileOperationCallbackAsEntryActionCallback(
237 const FileOperationCallback& callback,
238 google_apis::DriveApiErrorCode error) {
239 callback.Run(GDataToFileError(error));
242 // Checks if the |entry|'s hash is included in |hashes|.
243 bool CheckHashes(const std::set<std::string>& hashes,
244 const ResourceEntry& entry) {
245 return hashes.find(entry.file_specific_info().md5()) != hashes.end();
248 // Runs |callback| with |error| and the list of HashAndFilePath obtained from
249 // |original_result|.
250 void RunSearchByHashesCallback(
251 const SearchByHashesCallback& callback,
252 FileError error,
253 scoped_ptr<MetadataSearchResultVector> original_result) {
254 std::vector<HashAndFilePath> result;
255 if (error != FILE_ERROR_OK) {
256 callback.Run(error, result);
257 return;
259 for (const auto& search_result : *original_result) {
260 HashAndFilePath hash_and_path;
261 hash_and_path.hash = search_result.md5;
262 hash_and_path.path = search_result.path;
263 result.push_back(hash_and_path);
265 callback.Run(FILE_ERROR_OK, result);
268 } // namespace
270 struct FileSystem::CreateDirectoryParams {
271 base::FilePath directory_path;
272 bool is_exclusive;
273 bool is_recursive;
274 FileOperationCallback callback;
277 FileSystem::FileSystem(PrefService* pref_service,
278 EventLogger* logger,
279 internal::FileCache* cache,
280 JobScheduler* scheduler,
281 internal::ResourceMetadata* resource_metadata,
282 base::SequencedTaskRunner* blocking_task_runner,
283 base::SingleThreadTaskRunner* file_task_runner,
284 const base::FilePath& temporary_file_directory)
285 : pref_service_(pref_service),
286 logger_(logger),
287 cache_(cache),
288 scheduler_(scheduler),
289 resource_metadata_(resource_metadata),
290 last_update_check_error_(FILE_ERROR_OK),
291 blocking_task_runner_(blocking_task_runner),
292 file_task_runner_(file_task_runner),
293 temporary_file_directory_(temporary_file_directory),
294 weak_ptr_factory_(this) {
295 ResetComponents();
298 FileSystem::~FileSystem() {
299 DCHECK(thread_checker_.CalledOnValidThread());
301 directory_loader_->RemoveObserver(this);
302 change_list_loader_->RemoveObserver(this);
305 void FileSystem::Reset(const FileOperationCallback& callback) {
306 // Discard the current loader and operation objects and renew them. This is to
307 // avoid that changes initiated before the metadata reset is applied after the
308 // reset, which may cause an inconsistent state.
309 // TODO(kinaba): callbacks held in the subcomponents are discarded. We might
310 // want to have a way to abort and flush callbacks in in-flight operations.
311 ResetComponents();
313 base::PostTaskAndReplyWithResult(
314 blocking_task_runner_.get(),
315 FROM_HERE,
316 base::Bind(&ResetOnBlockingPool, resource_metadata_, cache_),
317 callback);
320 void FileSystem::ResetComponents() {
321 file_system::OperationDelegate* delegate = this;
323 about_resource_loader_.reset(new internal::AboutResourceLoader(scheduler_));
324 loader_controller_.reset(new internal::LoaderController);
325 change_list_loader_.reset(new internal::ChangeListLoader(
326 logger_,
327 blocking_task_runner_.get(),
328 resource_metadata_,
329 scheduler_,
330 about_resource_loader_.get(),
331 loader_controller_.get()));
332 change_list_loader_->AddObserver(this);
333 directory_loader_.reset(new internal::DirectoryLoader(
334 logger_,
335 blocking_task_runner_.get(),
336 resource_metadata_,
337 scheduler_,
338 about_resource_loader_.get(),
339 loader_controller_.get()));
340 directory_loader_->AddObserver(this);
342 sync_client_.reset(new internal::SyncClient(blocking_task_runner_.get(),
343 delegate,
344 scheduler_,
345 resource_metadata_,
346 cache_,
347 loader_controller_.get(),
348 temporary_file_directory_));
350 copy_operation_.reset(
351 new file_system::CopyOperation(blocking_task_runner_.get(),
352 delegate,
353 scheduler_,
354 resource_metadata_,
355 cache_));
356 create_directory_operation_.reset(new file_system::CreateDirectoryOperation(
357 blocking_task_runner_.get(), delegate, resource_metadata_));
358 create_file_operation_.reset(
359 new file_system::CreateFileOperation(blocking_task_runner_.get(),
360 delegate,
361 resource_metadata_));
362 move_operation_.reset(
363 new file_system::MoveOperation(blocking_task_runner_.get(),
364 delegate,
365 resource_metadata_));
366 open_file_operation_.reset(
367 new file_system::OpenFileOperation(blocking_task_runner_.get(),
368 delegate,
369 scheduler_,
370 resource_metadata_,
371 cache_,
372 temporary_file_directory_));
373 remove_operation_.reset(
374 new file_system::RemoveOperation(blocking_task_runner_.get(),
375 delegate,
376 resource_metadata_,
377 cache_));
378 touch_operation_.reset(new file_system::TouchOperation(
379 blocking_task_runner_.get(), delegate, resource_metadata_));
380 truncate_operation_.reset(
381 new file_system::TruncateOperation(blocking_task_runner_.get(),
382 delegate,
383 scheduler_,
384 resource_metadata_,
385 cache_,
386 temporary_file_directory_));
387 download_operation_.reset(
388 new file_system::DownloadOperation(blocking_task_runner_.get(),
389 delegate,
390 scheduler_,
391 resource_metadata_,
392 cache_,
393 temporary_file_directory_));
394 search_operation_.reset(new file_system::SearchOperation(
395 blocking_task_runner_.get(), scheduler_, resource_metadata_,
396 loader_controller_.get()));
397 get_file_for_saving_operation_.reset(
398 new file_system::GetFileForSavingOperation(
399 logger_, blocking_task_runner_.get(), file_task_runner_.get(),
400 delegate, scheduler_, resource_metadata_, cache_,
401 temporary_file_directory_));
402 set_property_operation_.reset(new file_system::SetPropertyOperation(
403 blocking_task_runner_.get(), delegate, resource_metadata_));
406 void FileSystem::CheckForUpdates() {
407 DCHECK(thread_checker_.CalledOnValidThread());
408 DVLOG(1) << "CheckForUpdates";
410 change_list_loader_->CheckForUpdates(
411 base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr()));
414 void FileSystem::OnUpdateChecked(FileError error) {
415 DCHECK(thread_checker_.CalledOnValidThread());
416 DVLOG(1) << "CheckForUpdates finished: " << FileErrorToString(error);
417 last_update_check_time_ = base::Time::Now();
418 last_update_check_error_ = error;
421 void FileSystem::AddObserver(FileSystemObserver* observer) {
422 DCHECK(thread_checker_.CalledOnValidThread());
423 observers_.AddObserver(observer);
426 void FileSystem::RemoveObserver(FileSystemObserver* observer) {
427 DCHECK(thread_checker_.CalledOnValidThread());
428 observers_.RemoveObserver(observer);
431 void FileSystem::TransferFileFromLocalToRemote(
432 const base::FilePath& local_src_file_path,
433 const base::FilePath& remote_dest_file_path,
434 const FileOperationCallback& callback) {
435 DCHECK(thread_checker_.CalledOnValidThread());
436 DCHECK(!callback.is_null());
437 copy_operation_->TransferFileFromLocalToRemote(local_src_file_path,
438 remote_dest_file_path,
439 callback);
442 void FileSystem::Copy(const base::FilePath& src_file_path,
443 const base::FilePath& dest_file_path,
444 bool preserve_last_modified,
445 const FileOperationCallback& callback) {
446 DCHECK(thread_checker_.CalledOnValidThread());
447 DCHECK(!callback.is_null());
448 copy_operation_->Copy(
449 src_file_path, dest_file_path, preserve_last_modified, callback);
452 void FileSystem::Move(const base::FilePath& src_file_path,
453 const base::FilePath& dest_file_path,
454 const FileOperationCallback& callback) {
455 DCHECK(thread_checker_.CalledOnValidThread());
456 DCHECK(!callback.is_null());
457 move_operation_->Move(src_file_path, dest_file_path, callback);
460 void FileSystem::Remove(const base::FilePath& file_path,
461 bool is_recursive,
462 const FileOperationCallback& callback) {
463 DCHECK(thread_checker_.CalledOnValidThread());
464 DCHECK(!callback.is_null());
465 remove_operation_->Remove(file_path, is_recursive, callback);
468 void FileSystem::CreateDirectory(
469 const base::FilePath& directory_path,
470 bool is_exclusive,
471 bool is_recursive,
472 const FileOperationCallback& callback) {
473 DCHECK(thread_checker_.CalledOnValidThread());
474 DCHECK(!callback.is_null());
476 CreateDirectoryParams params;
477 params.directory_path = directory_path;
478 params.is_exclusive = is_exclusive;
479 params.is_recursive = is_recursive;
480 params.callback = callback;
482 // Ensure its parent directory is loaded to the local metadata.
483 ReadDirectory(directory_path.DirName(),
484 ReadDirectoryEntriesCallback(),
485 base::Bind(&FileSystem::CreateDirectoryAfterRead,
486 weak_ptr_factory_.GetWeakPtr(), params));
489 void FileSystem::CreateDirectoryAfterRead(const CreateDirectoryParams& params,
490 FileError error) {
491 DCHECK(thread_checker_.CalledOnValidThread());
492 DCHECK(!params.callback.is_null());
494 DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. "
495 << FileErrorToString(error);
497 create_directory_operation_->CreateDirectory(
498 params.directory_path, params.is_exclusive, params.is_recursive,
499 params.callback);
502 void FileSystem::CreateFile(const base::FilePath& file_path,
503 bool is_exclusive,
504 const std::string& mime_type,
505 const FileOperationCallback& callback) {
506 DCHECK(thread_checker_.CalledOnValidThread());
507 DCHECK(!callback.is_null());
508 create_file_operation_->CreateFile(
509 file_path, is_exclusive, mime_type, callback);
512 void FileSystem::TouchFile(const base::FilePath& file_path,
513 const base::Time& last_access_time,
514 const base::Time& last_modified_time,
515 const FileOperationCallback& callback) {
516 DCHECK(thread_checker_.CalledOnValidThread());
517 DCHECK(!callback.is_null());
518 touch_operation_->TouchFile(
519 file_path, last_access_time, last_modified_time, callback);
522 void FileSystem::TruncateFile(const base::FilePath& file_path,
523 int64 length,
524 const FileOperationCallback& callback) {
525 DCHECK(thread_checker_.CalledOnValidThread());
526 DCHECK(!callback.is_null());
527 truncate_operation_->Truncate(file_path, length, callback);
530 void FileSystem::Pin(const base::FilePath& file_path,
531 const FileOperationCallback& callback) {
532 DCHECK(thread_checker_.CalledOnValidThread());
533 DCHECK(!callback.is_null());
535 std::string* local_id = new std::string;
536 base::PostTaskAndReplyWithResult(
537 blocking_task_runner_.get(),
538 FROM_HERE,
539 base::Bind(&PinInternal, resource_metadata_, cache_, file_path, local_id),
540 base::Bind(&FileSystem::FinishPin,
541 weak_ptr_factory_.GetWeakPtr(),
542 callback,
543 base::Owned(local_id)));
546 void FileSystem::FinishPin(const FileOperationCallback& callback,
547 const std::string* local_id,
548 FileError error) {
549 DCHECK(thread_checker_.CalledOnValidThread());
550 DCHECK(!callback.is_null());
552 if (error == FILE_ERROR_OK)
553 sync_client_->AddFetchTask(*local_id);
554 callback.Run(error);
557 void FileSystem::Unpin(const base::FilePath& file_path,
558 const FileOperationCallback& callback) {
559 DCHECK(thread_checker_.CalledOnValidThread());
560 DCHECK(!callback.is_null());
562 std::string* local_id = new std::string;
563 base::PostTaskAndReplyWithResult(
564 blocking_task_runner_.get(),
565 FROM_HERE,
566 base::Bind(
567 &UnpinInternal, resource_metadata_, cache_, file_path, local_id),
568 base::Bind(&FileSystem::FinishUnpin,
569 weak_ptr_factory_.GetWeakPtr(),
570 callback,
571 base::Owned(local_id)));
574 void FileSystem::FinishUnpin(const FileOperationCallback& callback,
575 const std::string* local_id,
576 FileError error) {
577 DCHECK(thread_checker_.CalledOnValidThread());
578 DCHECK(!callback.is_null());
580 if (error == FILE_ERROR_OK)
581 sync_client_->RemoveFetchTask(*local_id);
582 callback.Run(error);
585 void FileSystem::GetFile(const base::FilePath& file_path,
586 const GetFileCallback& callback) {
587 DCHECK(thread_checker_.CalledOnValidThread());
588 DCHECK(!callback.is_null());
590 download_operation_->EnsureFileDownloadedByPath(
591 file_path,
592 ClientContext(USER_INITIATED),
593 GetFileContentInitializedCallback(),
594 google_apis::GetContentCallback(),
595 callback);
598 void FileSystem::GetFileForSaving(const base::FilePath& file_path,
599 const GetFileCallback& callback) {
600 DCHECK(thread_checker_.CalledOnValidThread());
601 DCHECK(!callback.is_null());
603 get_file_for_saving_operation_->GetFileForSaving(file_path, callback);
606 base::Closure FileSystem::GetFileContent(
607 const base::FilePath& file_path,
608 const GetFileContentInitializedCallback& initialized_callback,
609 const google_apis::GetContentCallback& get_content_callback,
610 const FileOperationCallback& completion_callback) {
611 DCHECK(thread_checker_.CalledOnValidThread());
612 DCHECK(!initialized_callback.is_null());
613 DCHECK(!get_content_callback.is_null());
614 DCHECK(!completion_callback.is_null());
616 return download_operation_->EnsureFileDownloadedByPath(
617 file_path,
618 ClientContext(USER_INITIATED),
619 initialized_callback,
620 get_content_callback,
621 base::Bind(&GetFileCallbackToFileOperationCallbackAdapter,
622 completion_callback));
625 void FileSystem::GetResourceEntry(
626 const base::FilePath& file_path,
627 const GetResourceEntryCallback& callback) {
628 DCHECK(thread_checker_.CalledOnValidThread());
629 DCHECK(!callback.is_null());
631 ReadDirectory(file_path.DirName(),
632 ReadDirectoryEntriesCallback(),
633 base::Bind(&FileSystem::GetResourceEntryAfterRead,
634 weak_ptr_factory_.GetWeakPtr(),
635 file_path,
636 callback));
639 void FileSystem::GetResourceEntryAfterRead(
640 const base::FilePath& file_path,
641 const GetResourceEntryCallback& callback,
642 FileError error) {
643 DCHECK(thread_checker_.CalledOnValidThread());
644 DCHECK(!callback.is_null());
646 DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. "
647 << FileErrorToString(error);
649 scoped_ptr<ResourceEntry> entry(new ResourceEntry);
650 ResourceEntry* entry_ptr = entry.get();
651 base::PostTaskAndReplyWithResult(
652 blocking_task_runner_.get(),
653 FROM_HERE,
654 base::Bind(&GetLocallyStoredResourceEntry,
655 resource_metadata_,
656 cache_,
657 file_path,
658 entry_ptr),
659 base::Bind(&RunGetResourceEntryCallback, callback, base::Passed(&entry)));
662 void FileSystem::ReadDirectory(
663 const base::FilePath& directory_path,
664 const ReadDirectoryEntriesCallback& entries_callback_in,
665 const FileOperationCallback& completion_callback) {
666 DCHECK(thread_checker_.CalledOnValidThread());
667 DCHECK(!completion_callback.is_null());
669 const bool hide_hosted_docs =
670 pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles);
671 ReadDirectoryEntriesCallback entries_callback = entries_callback_in;
672 if (!entries_callback.is_null() && hide_hosted_docs)
673 entries_callback = base::Bind(&FilterHostedDocuments, entries_callback);
675 directory_loader_->ReadDirectory(
676 directory_path, entries_callback, completion_callback);
678 // Also start loading all of the user's contents.
679 change_list_loader_->LoadIfNeeded(
680 base::Bind(&util::EmptyFileOperationCallback));
683 void FileSystem::GetAvailableSpace(
684 const GetAvailableSpaceCallback& callback) {
685 DCHECK(thread_checker_.CalledOnValidThread());
686 DCHECK(!callback.is_null());
688 about_resource_loader_->GetAboutResource(
689 base::Bind(&FileSystem::OnGetAboutResource,
690 weak_ptr_factory_.GetWeakPtr(),
691 callback));
694 void FileSystem::OnGetAboutResource(
695 const GetAvailableSpaceCallback& callback,
696 google_apis::DriveApiErrorCode status,
697 scoped_ptr<google_apis::AboutResource> about_resource) {
698 DCHECK(thread_checker_.CalledOnValidThread());
699 DCHECK(!callback.is_null());
701 FileError error = GDataToFileError(status);
702 if (error != FILE_ERROR_OK) {
703 callback.Run(error, -1, -1);
704 return;
706 DCHECK(about_resource);
708 callback.Run(FILE_ERROR_OK, about_resource->quota_bytes_total(),
709 about_resource->quota_bytes_used_aggregate());
712 void FileSystem::GetShareUrl(const base::FilePath& file_path,
713 const GURL& embed_origin,
714 const GetShareUrlCallback& callback) {
715 DCHECK(thread_checker_.CalledOnValidThread());
716 DCHECK(!callback.is_null());
718 // Resolve the resource id.
719 ResourceEntry* entry = new ResourceEntry;
720 base::PostTaskAndReplyWithResult(
721 blocking_task_runner_.get(),
722 FROM_HERE,
723 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath,
724 base::Unretained(resource_metadata_),
725 file_path,
726 entry),
727 base::Bind(&FileSystem::GetShareUrlAfterGetResourceEntry,
728 weak_ptr_factory_.GetWeakPtr(),
729 file_path,
730 embed_origin,
731 callback,
732 base::Owned(entry)));
735 void FileSystem::GetShareUrlAfterGetResourceEntry(
736 const base::FilePath& file_path,
737 const GURL& embed_origin,
738 const GetShareUrlCallback& callback,
739 ResourceEntry* entry,
740 FileError error) {
741 DCHECK(thread_checker_.CalledOnValidThread());
742 DCHECK(!callback.is_null());
744 if (error != FILE_ERROR_OK) {
745 callback.Run(error, GURL());
746 return;
748 if (entry->resource_id().empty()) {
749 // This entry does not exist on the server. Just return.
750 callback.Run(FILE_ERROR_FAILED, GURL());
751 return;
754 scheduler_->GetShareUrl(
755 entry->resource_id(),
756 embed_origin,
757 ClientContext(USER_INITIATED),
758 base::Bind(&FileSystem::OnGetResourceEntryForGetShareUrl,
759 weak_ptr_factory_.GetWeakPtr(),
760 callback));
763 void FileSystem::OnGetResourceEntryForGetShareUrl(
764 const GetShareUrlCallback& callback,
765 google_apis::DriveApiErrorCode status,
766 const GURL& share_url) {
767 DCHECK(thread_checker_.CalledOnValidThread());
768 DCHECK(!callback.is_null());
770 FileError error = GDataToFileError(status);
771 if (error != FILE_ERROR_OK) {
772 callback.Run(error, GURL());
773 return;
776 if (share_url.is_empty()) {
777 callback.Run(FILE_ERROR_FAILED, GURL());
778 return;
781 callback.Run(FILE_ERROR_OK, share_url);
784 void FileSystem::Search(const std::string& search_query,
785 const GURL& next_link,
786 const SearchCallback& callback) {
787 DCHECK(thread_checker_.CalledOnValidThread());
788 DCHECK(!callback.is_null());
789 search_operation_->Search(search_query, next_link, callback);
792 void FileSystem::SearchMetadata(const std::string& query,
793 int options,
794 int at_most_num_matches,
795 const SearchMetadataCallback& callback) {
796 DCHECK(thread_checker_.CalledOnValidThread());
798 // TODO(satorux): Stop handling hide_hosted_docs here. crbug.com/256520.
799 if (pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles))
800 options |= SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS;
802 drive::internal::SearchMetadata(
803 blocking_task_runner_, resource_metadata_, query,
804 base::Bind(&drive::internal::MatchesType, options), at_most_num_matches,
805 callback);
808 void FileSystem::SearchByHashes(const std::set<std::string>& hashes,
809 const SearchByHashesCallback& callback) {
810 DCHECK(thread_checker_.CalledOnValidThread());
811 drive::internal::SearchMetadata(
812 blocking_task_runner_, resource_metadata_,
813 /* any file name */ "", base::Bind(&CheckHashes, hashes),
814 std::numeric_limits<size_t>::max(),
815 base::Bind(&RunSearchByHashesCallback, callback));
818 void FileSystem::OnFileChangedByOperation(const FileChange& changed_files) {
819 DCHECK(thread_checker_.CalledOnValidThread());
821 FOR_EACH_OBSERVER(
822 FileSystemObserver, observers_, OnFileChanged(changed_files));
825 void FileSystem::OnEntryUpdatedByOperation(const ClientContext& context,
826 const std::string& local_id) {
827 sync_client_->AddUpdateTask(context, local_id);
830 void FileSystem::OnDriveSyncError(file_system::DriveSyncErrorType type,
831 const std::string& local_id) {
832 base::FilePath* file_path = new base::FilePath;
833 base::PostTaskAndReplyWithResult(
834 blocking_task_runner_.get(),
835 FROM_HERE,
836 base::Bind(&internal::ResourceMetadata::GetFilePath,
837 base::Unretained(resource_metadata_),
838 local_id,
839 file_path),
840 base::Bind(&FileSystem::OnDriveSyncErrorAfterGetFilePath,
841 weak_ptr_factory_.GetWeakPtr(),
842 type,
843 base::Owned(file_path)));
846 void FileSystem::OnDriveSyncErrorAfterGetFilePath(
847 file_system::DriveSyncErrorType type,
848 const base::FilePath* file_path,
849 FileError error) {
850 if (error != FILE_ERROR_OK)
851 return;
852 FOR_EACH_OBSERVER(FileSystemObserver,
853 observers_,
854 OnDriveSyncError(type, *file_path));
857 bool FileSystem::WaitForSyncComplete(const std::string& local_id,
858 const FileOperationCallback& callback) {
859 return sync_client_->WaitForUpdateTaskToComplete(local_id, callback);
862 void FileSystem::OnDirectoryReloaded(const base::FilePath& directory_path) {
863 DCHECK(thread_checker_.CalledOnValidThread());
865 FOR_EACH_OBSERVER(
866 FileSystemObserver, observers_, OnDirectoryChanged(directory_path));
869 void FileSystem::OnFileChanged(const FileChange& changed_files) {
870 DCHECK(thread_checker_.CalledOnValidThread());
872 FOR_EACH_OBSERVER(
873 FileSystemObserver, observers_, OnFileChanged(changed_files));
876 void FileSystem::OnLoadFromServerComplete() {
877 DCHECK(thread_checker_.CalledOnValidThread());
879 sync_client_->StartCheckingExistingPinnedFiles();
882 void FileSystem::OnInitialLoadComplete() {
883 DCHECK(thread_checker_.CalledOnValidThread());
885 blocking_task_runner_->PostTask(FROM_HERE,
886 base::Bind(&internal::RemoveStaleCacheFiles,
887 cache_,
888 resource_metadata_));
889 sync_client_->StartProcessingBacklog();
892 void FileSystem::GetMetadata(
893 const GetFilesystemMetadataCallback& callback) {
894 DCHECK(thread_checker_.CalledOnValidThread());
895 DCHECK(!callback.is_null());
897 FileSystemMetadata metadata;
898 metadata.refreshing = change_list_loader_->IsRefreshing();
900 // Metadata related to delta update.
901 metadata.last_update_check_time = last_update_check_time_;
902 metadata.last_update_check_error = last_update_check_error_;
904 int64* largest_changestamp = new int64(0);
905 base::PostTaskAndReplyWithResult(
906 blocking_task_runner_.get(),
907 FROM_HERE,
908 base::Bind(&internal::ResourceMetadata::GetLargestChangestamp,
909 base::Unretained(resource_metadata_),
910 largest_changestamp),
911 base::Bind(&OnGetLargestChangestamp,
912 metadata,
913 callback,
914 base::Owned(largest_changestamp)));
917 void FileSystem::MarkCacheFileAsMounted(
918 const base::FilePath& drive_file_path,
919 const MarkMountedCallback& callback) {
920 DCHECK(thread_checker_.CalledOnValidThread());
921 DCHECK(!callback.is_null());
923 base::FilePath* cache_file_path = new base::FilePath;
924 base::PostTaskAndReplyWithResult(
925 blocking_task_runner_.get(),
926 FROM_HERE,
927 base::Bind(&MarkCacheFileAsMountedInternal,
928 resource_metadata_,
929 cache_,
930 drive_file_path,
931 cache_file_path),
932 base::Bind(
933 &RunMarkMountedCallback, callback, base::Owned(cache_file_path)));
936 void FileSystem::MarkCacheFileAsUnmounted(
937 const base::FilePath& cache_file_path,
938 const FileOperationCallback& callback) {
939 DCHECK(thread_checker_.CalledOnValidThread());
940 DCHECK(!callback.is_null());
942 if (!cache_->IsUnderFileCacheDirectory(cache_file_path)) {
943 callback.Run(FILE_ERROR_FAILED);
944 return;
947 base::PostTaskAndReplyWithResult(
948 blocking_task_runner_.get(),
949 FROM_HERE,
950 base::Bind(&internal::FileCache::MarkAsUnmounted,
951 base::Unretained(cache_),
952 cache_file_path),
953 callback);
956 void FileSystem::AddPermission(const base::FilePath& drive_file_path,
957 const std::string& email,
958 google_apis::drive::PermissionRole role,
959 const FileOperationCallback& callback) {
960 DCHECK(thread_checker_.CalledOnValidThread());
961 DCHECK(!callback.is_null());
963 // Resolve the resource id.
964 ResourceEntry* const entry = new ResourceEntry;
965 base::PostTaskAndReplyWithResult(
966 blocking_task_runner_.get(),
967 FROM_HERE,
968 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath,
969 base::Unretained(resource_metadata_),
970 drive_file_path,
971 entry),
972 base::Bind(&FileSystem::AddPermissionAfterGetResourceEntry,
973 weak_ptr_factory_.GetWeakPtr(),
974 email,
975 role,
976 callback,
977 base::Owned(entry)));
980 void FileSystem::AddPermissionAfterGetResourceEntry(
981 const std::string& email,
982 google_apis::drive::PermissionRole role,
983 const FileOperationCallback& callback,
984 ResourceEntry* entry,
985 FileError error) {
986 DCHECK(thread_checker_.CalledOnValidThread());
988 if (error != FILE_ERROR_OK) {
989 callback.Run(error);
990 return;
993 scheduler_->AddPermission(
994 entry->resource_id(),
995 email,
996 role,
997 base::Bind(&RunFileOperationCallbackAsEntryActionCallback, callback));
1000 void FileSystem::SetProperty(
1001 const base::FilePath& drive_file_path,
1002 google_apis::drive::Property::Visibility visibility,
1003 const std::string& key,
1004 const std::string& value,
1005 const FileOperationCallback& callback) {
1006 DCHECK(thread_checker_.CalledOnValidThread());
1007 DCHECK(!callback.is_null());
1009 set_property_operation_->SetProperty(drive_file_path, visibility, key, value,
1010 callback);
1013 void FileSystem::OpenFile(const base::FilePath& file_path,
1014 OpenMode open_mode,
1015 const std::string& mime_type,
1016 const OpenFileCallback& callback) {
1017 DCHECK(thread_checker_.CalledOnValidThread());
1018 DCHECK(!callback.is_null());
1020 open_file_operation_->OpenFile(file_path, open_mode, mime_type, callback);
1023 void FileSystem::GetPathFromResourceId(const std::string& resource_id,
1024 const GetFilePathCallback& callback) {
1025 DCHECK(thread_checker_.CalledOnValidThread());
1026 DCHECK(!callback.is_null());
1028 base::FilePath* const file_path = new base::FilePath();
1029 base::PostTaskAndReplyWithResult(
1030 blocking_task_runner_.get(),
1031 FROM_HERE,
1032 base::Bind(&GetPathFromResourceIdOnBlockingPool,
1033 resource_metadata_,
1034 resource_id,
1035 file_path),
1036 base::Bind(&GetPathFromResourceIdAfterGetPath,
1037 base::Owned(file_path),
1038 callback));
1041 void FileSystem::FreeDiskSpaceIfNeededFor(
1042 int64 num_bytes,
1043 const FreeDiskSpaceCallback& callback) {
1044 DCHECK(thread_checker_.CalledOnValidThread());
1045 DCHECK(!callback.is_null());
1046 base::PostTaskAndReplyWithResult(
1047 blocking_task_runner_.get(), FROM_HERE,
1048 base::Bind(&FreeDiskSpaceIfNeededForOnBlockingPool, cache_, num_bytes),
1049 callback);
1052 void FileSystem::CalculateEvictableCacheSize(
1053 const EvictableCacheSizeCallback& callback) {
1054 DCHECK(thread_checker_.CalledOnValidThread());
1055 DCHECK(!callback.is_null());
1056 base::PostTaskAndReplyWithResult(
1057 blocking_task_runner_.get(), FROM_HERE,
1058 base::Bind(&CalculateEvictableCacheSizeOnBlockingPool, cache_), callback);
1060 } // namespace drive