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 "chrome/browser/chromeos/drive/file_system.h"
8 #include "base/file_util.h"
9 #include "base/platform_file.h"
10 #include "base/prefs/pref_service.h"
11 #include "chrome/browser/chromeos/drive/change_list_loader.h"
12 #include "chrome/browser/chromeos/drive/drive.pb.h"
13 #include "chrome/browser/chromeos/drive/file_cache.h"
14 #include "chrome/browser/chromeos/drive/file_system/copy_operation.h"
15 #include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h"
16 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
17 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
18 #include "chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h"
19 #include "chrome/browser/chromeos/drive/file_system/move_operation.h"
20 #include "chrome/browser/chromeos/drive/file_system/open_file_operation.h"
21 #include "chrome/browser/chromeos/drive/file_system/remove_operation.h"
22 #include "chrome/browser/chromeos/drive/file_system/search_operation.h"
23 #include "chrome/browser/chromeos/drive/file_system/touch_operation.h"
24 #include "chrome/browser/chromeos/drive/file_system/truncate_operation.h"
25 #include "chrome/browser/chromeos/drive/file_system_observer.h"
26 #include "chrome/browser/chromeos/drive/file_system_util.h"
27 #include "chrome/browser/chromeos/drive/job_scheduler.h"
28 #include "chrome/browser/chromeos/drive/remove_stale_cache_files.h"
29 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
30 #include "chrome/browser/chromeos/drive/search_metadata.h"
31 #include "chrome/browser/chromeos/drive/sync_client.h"
32 #include "chrome/browser/drive/drive_service_interface.h"
33 #include "chrome/common/pref_names.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "google_apis/drive/drive_api_parser.h"
37 using content::BrowserThread;
42 // Gets a ResourceEntry from the metadata, and overwrites its file info when the
43 // cached file is dirty.
44 FileError GetLocallyStoredResourceEntry(
45 internal::ResourceMetadata* resource_metadata,
46 internal::FileCache* cache,
47 const base::FilePath& file_path,
48 ResourceEntry* entry) {
50 FileError error = resource_metadata->GetIdByPath(file_path, &local_id);
51 if (error != FILE_ERROR_OK)
54 error = resource_metadata->GetResourceEntryById(local_id, entry);
55 if (error != FILE_ERROR_OK)
58 // For entries that will never be cached, use the original resource entry
60 if (!entry->has_file_specific_info() ||
61 entry->file_specific_info().is_hosted_document())
64 // When cache is not found, use the original resource entry as is.
65 FileCacheEntry cache_entry;
66 if (!cache->GetCacheEntry(local_id, &cache_entry))
69 // When cache is non-dirty and obsolete (old hash), use the original entry.
70 if (!cache_entry.is_dirty() &&
71 entry->file_specific_info().md5() != cache_entry.md5())
74 // If there's a valid cache, obtain the file info from the cache file itself.
75 base::FilePath local_cache_path;
76 error = cache->GetFile(local_id, &local_cache_path);
77 if (error != FILE_ERROR_OK)
80 base::File::Info file_info;
81 if (!base::GetFileInfo(local_cache_path, &file_info))
82 return FILE_ERROR_NOT_FOUND;
84 // TODO(hashimoto): crbug.com/346625. Also reflect timestamps.
85 entry->mutable_file_info()->set_size(file_info.size);
89 // Runs the callback with parameters.
90 void RunGetResourceEntryCallback(const GetResourceEntryCallback& callback,
91 scoped_ptr<ResourceEntry> entry,
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
94 DCHECK(!callback.is_null());
96 if (error != FILE_ERROR_OK)
98 callback.Run(error, entry.Pass());
101 // Used to implement Pin().
102 FileError PinInternal(internal::ResourceMetadata* resource_metadata,
103 internal::FileCache* cache,
104 const base::FilePath& file_path,
105 std::string* local_id) {
106 FileError error = resource_metadata->GetIdByPath(file_path, local_id);
107 if (error != FILE_ERROR_OK)
111 error = resource_metadata->GetResourceEntryById(*local_id, &entry);
112 if (error != FILE_ERROR_OK)
115 // TODO(hashimoto): Support pinning directories. crbug.com/127831
116 if (entry.file_info().is_directory())
117 return FILE_ERROR_NOT_A_FILE;
119 return cache->Pin(*local_id);
122 // Used to implement Unpin().
123 FileError UnpinInternal(internal::ResourceMetadata* resource_metadata,
124 internal::FileCache* cache,
125 const base::FilePath& file_path,
126 std::string* local_id) {
127 FileError error = resource_metadata->GetIdByPath(file_path, local_id);
128 if (error != FILE_ERROR_OK)
131 return cache->Unpin(*local_id);
134 // Used to implement MarkCacheFileAsMounted().
135 FileError MarkCacheFileAsMountedInternal(
136 internal::ResourceMetadata* resource_metadata,
137 internal::FileCache* cache,
138 const base::FilePath& drive_file_path,
139 base::FilePath* cache_file_path) {
140 std::string local_id;
141 FileError error = resource_metadata->GetIdByPath(drive_file_path, &local_id);
142 if (error != FILE_ERROR_OK)
145 return cache->MarkAsMounted(local_id, cache_file_path);
148 // Runs the callback with arguments.
149 void RunMarkMountedCallback(const MarkMountedCallback& callback,
150 base::FilePath* cache_file_path,
152 DCHECK(!callback.is_null());
153 callback.Run(error, *cache_file_path);
156 // Used to implement GetCacheEntry.
157 bool GetCacheEntryInternal(internal::ResourceMetadata* resource_metadata,
158 internal::FileCache* cache,
159 const base::FilePath& drive_file_path,
160 FileCacheEntry* cache_entry) {
162 if (resource_metadata->GetIdByPath(drive_file_path, &id) != FILE_ERROR_OK)
165 return cache->GetCacheEntry(id, cache_entry);
168 // Runs the callback with arguments.
169 void RunGetCacheEntryCallback(const GetCacheEntryCallback& callback,
170 const FileCacheEntry* cache_entry,
172 DCHECK(!callback.is_null());
173 callback.Run(success, *cache_entry);
176 // Callback for ResourceMetadata::GetLargestChangestamp.
177 // |callback| must not be null.
178 void OnGetLargestChangestamp(
179 FileSystemMetadata metadata, // Will be modified.
180 const GetFilesystemMetadataCallback& callback,
181 int64 largest_changestamp) {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
183 DCHECK(!callback.is_null());
185 metadata.largest_changestamp = largest_changestamp;
186 callback.Run(metadata);
189 // Thin adapter to map GetFileCallback to FileOperationCallback.
190 void GetFileCallbackToFileOperationCallbackAdapter(
191 const FileOperationCallback& callback,
193 const base::FilePath& unused_file_path,
194 scoped_ptr<ResourceEntry> unused_entry) {
198 // Clears |resource_metadata| and |cache|.
199 FileError ResetOnBlockingPool(internal::ResourceMetadata* resource_metadata,
200 internal::FileCache* cache) {
201 FileError error = resource_metadata->Reset();
202 if (error != FILE_ERROR_OK)
204 return cache->ClearAll() ? FILE_ERROR_OK : FILE_ERROR_FAILED;
209 FileSystem::FileSystem(
210 PrefService* pref_service,
212 internal::FileCache* cache,
213 DriveServiceInterface* drive_service,
214 JobScheduler* scheduler,
215 internal::ResourceMetadata* resource_metadata,
216 base::SequencedTaskRunner* blocking_task_runner,
217 const base::FilePath& temporary_file_directory)
218 : pref_service_(pref_service),
221 drive_service_(drive_service),
222 scheduler_(scheduler),
223 resource_metadata_(resource_metadata),
224 last_update_check_error_(FILE_ERROR_OK),
225 blocking_task_runner_(blocking_task_runner),
226 temporary_file_directory_(temporary_file_directory),
227 weak_ptr_factory_(this) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
233 FileSystem::~FileSystem() {
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
236 change_list_loader_->RemoveObserver(this);
239 void FileSystem::Reset(const FileOperationCallback& callback) {
240 // Discard the current loader and operation objects and renew them. This is to
241 // avoid that changes initiated before the metadata reset is applied after the
242 // reset, which may cause an inconsistent state.
243 // TODO(kinaba): callbacks held in the subcomponents are discarded. We might
244 // want to have a way to abort and flush callbacks in in-flight operations.
247 base::PostTaskAndReplyWithResult(
248 blocking_task_runner_,
250 base::Bind(&ResetOnBlockingPool, resource_metadata_, cache_),
254 void FileSystem::ResetComponents() {
255 file_system::OperationObserver* observer = this;
257 about_resource_loader_.reset(new internal::AboutResourceLoader(scheduler_));
258 loader_controller_.reset(new internal::LoaderController);
259 change_list_loader_.reset(new internal::ChangeListLoader(
261 blocking_task_runner_.get(),
265 about_resource_loader_.get(),
266 loader_controller_.get()));
267 change_list_loader_->AddObserver(this);
269 sync_client_.reset(new internal::SyncClient(blocking_task_runner_.get(),
274 loader_controller_.get(),
275 temporary_file_directory_));
277 copy_operation_.reset(
278 new file_system::CopyOperation(
279 blocking_task_runner_.get(),
284 drive_service_->GetResourceIdCanonicalizer()));
285 create_directory_operation_.reset(new file_system::CreateDirectoryOperation(
286 blocking_task_runner_.get(), observer, resource_metadata_));
287 create_file_operation_.reset(
288 new file_system::CreateFileOperation(blocking_task_runner_.get(),
290 resource_metadata_));
291 move_operation_.reset(
292 new file_system::MoveOperation(blocking_task_runner_.get(),
294 resource_metadata_));
295 open_file_operation_.reset(
296 new file_system::OpenFileOperation(blocking_task_runner_.get(),
301 temporary_file_directory_));
302 remove_operation_.reset(
303 new file_system::RemoveOperation(blocking_task_runner_.get(),
307 touch_operation_.reset(new file_system::TouchOperation(
308 blocking_task_runner_.get(), observer, resource_metadata_));
309 truncate_operation_.reset(
310 new file_system::TruncateOperation(blocking_task_runner_.get(),
315 temporary_file_directory_));
316 download_operation_.reset(
317 new file_system::DownloadOperation(blocking_task_runner_.get(),
322 temporary_file_directory_));
323 search_operation_.reset(new file_system::SearchOperation(
324 blocking_task_runner_.get(), scheduler_, resource_metadata_,
325 loader_controller_.get()));
326 get_file_for_saving_operation_.reset(
327 new file_system::GetFileForSavingOperation(logger_,
328 blocking_task_runner_.get(),
333 temporary_file_directory_));
336 void FileSystem::CheckForUpdates() {
337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
338 DVLOG(1) << "CheckForUpdates";
340 change_list_loader_->CheckForUpdates(
341 base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr()));
344 void FileSystem::OnUpdateChecked(FileError error) {
345 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
346 DVLOG(1) << "CheckForUpdates finished: " << FileErrorToString(error);
347 last_update_check_time_ = base::Time::Now();
348 last_update_check_error_ = error;
351 void FileSystem::AddObserver(FileSystemObserver* observer) {
352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
353 observers_.AddObserver(observer);
356 void FileSystem::RemoveObserver(FileSystemObserver* observer) {
357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
358 observers_.RemoveObserver(observer);
361 void FileSystem::TransferFileFromLocalToRemote(
362 const base::FilePath& local_src_file_path,
363 const base::FilePath& remote_dest_file_path,
364 const FileOperationCallback& callback) {
365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
366 DCHECK(!callback.is_null());
367 copy_operation_->TransferFileFromLocalToRemote(local_src_file_path,
368 remote_dest_file_path,
372 void FileSystem::Copy(const base::FilePath& src_file_path,
373 const base::FilePath& dest_file_path,
374 bool preserve_last_modified,
375 const FileOperationCallback& callback) {
376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
377 DCHECK(!callback.is_null());
378 copy_operation_->Copy(
379 src_file_path, dest_file_path, preserve_last_modified, callback);
382 void FileSystem::Move(const base::FilePath& src_file_path,
383 const base::FilePath& dest_file_path,
384 bool preserve_last_modified,
385 const FileOperationCallback& callback) {
386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
387 DCHECK(!callback.is_null());
388 move_operation_->Move(
389 src_file_path, dest_file_path, preserve_last_modified, callback);
392 void FileSystem::Remove(const base::FilePath& file_path,
394 const FileOperationCallback& callback) {
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
396 DCHECK(!callback.is_null());
397 remove_operation_->Remove(file_path, is_recursive, callback);
400 void FileSystem::CreateDirectory(
401 const base::FilePath& directory_path,
404 const FileOperationCallback& callback) {
405 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
406 DCHECK(!callback.is_null());
408 // Ensure its parent directory is loaded to the local metadata.
409 change_list_loader_->LoadDirectoryIfNeeded(
410 directory_path.DirName(),
411 base::Bind(&FileSystem::CreateDirectoryAfterLoad,
412 weak_ptr_factory_.GetWeakPtr(),
413 directory_path, is_exclusive, is_recursive, callback));
416 void FileSystem::CreateDirectoryAfterLoad(
417 const base::FilePath& directory_path,
420 const FileOperationCallback& callback,
421 FileError load_error) {
422 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
423 DCHECK(!callback.is_null());
425 DVLOG_IF(1, load_error != FILE_ERROR_OK) << "LoadDirectoryIfNeeded failed. "
426 << FileErrorToString(load_error);
428 create_directory_operation_->CreateDirectory(
429 directory_path, is_exclusive, is_recursive, callback);
432 void FileSystem::CreateFile(const base::FilePath& file_path,
434 const std::string& mime_type,
435 const FileOperationCallback& callback) {
436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
437 DCHECK(!callback.is_null());
438 create_file_operation_->CreateFile(
439 file_path, is_exclusive, mime_type, callback);
442 void FileSystem::TouchFile(const base::FilePath& file_path,
443 const base::Time& last_access_time,
444 const base::Time& last_modified_time,
445 const FileOperationCallback& callback) {
446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
447 DCHECK(!last_access_time.is_null());
448 DCHECK(!last_modified_time.is_null());
449 DCHECK(!callback.is_null());
450 touch_operation_->TouchFile(
451 file_path, last_access_time, last_modified_time, callback);
454 void FileSystem::TruncateFile(const base::FilePath& file_path,
456 const FileOperationCallback& callback) {
457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
458 DCHECK(!callback.is_null());
459 truncate_operation_->Truncate(file_path, length, callback);
462 void FileSystem::Pin(const base::FilePath& file_path,
463 const FileOperationCallback& callback) {
464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
465 DCHECK(!callback.is_null());
467 std::string* local_id = new std::string;
468 base::PostTaskAndReplyWithResult(
469 blocking_task_runner_,
471 base::Bind(&PinInternal, resource_metadata_, cache_, file_path, local_id),
472 base::Bind(&FileSystem::FinishPin,
473 weak_ptr_factory_.GetWeakPtr(),
475 base::Owned(local_id)));
478 void FileSystem::FinishPin(const FileOperationCallback& callback,
479 const std::string* local_id,
481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
482 DCHECK(!callback.is_null());
484 if (error == FILE_ERROR_OK)
485 sync_client_->AddFetchTask(*local_id);
489 void FileSystem::Unpin(const base::FilePath& file_path,
490 const FileOperationCallback& callback) {
491 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
492 DCHECK(!callback.is_null());
494 std::string* local_id = new std::string;
495 base::PostTaskAndReplyWithResult(
496 blocking_task_runner_,
498 base::Bind(&UnpinInternal,
503 base::Bind(&FileSystem::FinishUnpin,
504 weak_ptr_factory_.GetWeakPtr(),
506 base::Owned(local_id)));
509 void FileSystem::FinishUnpin(const FileOperationCallback& callback,
510 const std::string* local_id,
512 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
513 DCHECK(!callback.is_null());
515 if (error == FILE_ERROR_OK)
516 sync_client_->RemoveFetchTask(*local_id);
520 void FileSystem::GetFile(const base::FilePath& file_path,
521 const GetFileCallback& callback) {
522 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
523 DCHECK(!callback.is_null());
525 download_operation_->EnsureFileDownloadedByPath(
527 ClientContext(USER_INITIATED),
528 GetFileContentInitializedCallback(),
529 google_apis::GetContentCallback(),
533 void FileSystem::GetFileForSaving(const base::FilePath& file_path,
534 const GetFileCallback& callback) {
535 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
536 DCHECK(!callback.is_null());
538 get_file_for_saving_operation_->GetFileForSaving(file_path, callback);
541 void FileSystem::GetFileContent(
542 const base::FilePath& file_path,
543 const GetFileContentInitializedCallback& initialized_callback,
544 const google_apis::GetContentCallback& get_content_callback,
545 const FileOperationCallback& completion_callback) {
546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
547 DCHECK(!initialized_callback.is_null());
548 DCHECK(!get_content_callback.is_null());
549 DCHECK(!completion_callback.is_null());
551 download_operation_->EnsureFileDownloadedByPath(
553 ClientContext(USER_INITIATED),
554 initialized_callback,
555 get_content_callback,
556 base::Bind(&GetFileCallbackToFileOperationCallbackAdapter,
557 completion_callback));
560 void FileSystem::GetResourceEntry(
561 const base::FilePath& file_path,
562 const GetResourceEntryCallback& callback) {
563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
564 DCHECK(!callback.is_null());
566 change_list_loader_->LoadDirectoryIfNeeded(
568 base::Bind(&FileSystem::GetResourceEntryAfterLoad,
569 weak_ptr_factory_.GetWeakPtr(),
574 void FileSystem::GetResourceEntryAfterLoad(
575 const base::FilePath& file_path,
576 const GetResourceEntryCallback& callback,
578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
579 DCHECK(!callback.is_null());
581 DVLOG_IF(1, error != FILE_ERROR_OK) << "LoadDirectoryIfNeeded failed. "
582 << FileErrorToString(error);
584 scoped_ptr<ResourceEntry> entry(new ResourceEntry);
585 ResourceEntry* entry_ptr = entry.get();
586 base::PostTaskAndReplyWithResult(
587 blocking_task_runner_,
589 base::Bind(&GetLocallyStoredResourceEntry,
594 base::Bind(&RunGetResourceEntryCallback, callback, base::Passed(&entry)));
597 void FileSystem::ReadDirectory(
598 const base::FilePath& directory_path,
599 const ReadDirectoryCallback& callback) {
600 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
601 DCHECK(!callback.is_null());
603 change_list_loader_->LoadDirectoryIfNeeded(
605 base::Bind(&FileSystem::ReadDirectoryAfterLoad,
606 weak_ptr_factory_.GetWeakPtr(),
611 void FileSystem::ReadDirectoryAfterLoad(
612 const base::FilePath& directory_path,
613 const ReadDirectoryCallback& callback,
615 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
616 DCHECK(!callback.is_null());
618 DVLOG_IF(1, error != FILE_ERROR_OK) << "LoadDirectoryIfNeeded failed. "
619 << FileErrorToString(error);
621 ResourceEntryVector* entries = new ResourceEntryVector;
622 base::PostTaskAndReplyWithResult(
623 blocking_task_runner_.get(),
625 base::Bind(&internal::ResourceMetadata::ReadDirectoryByPath,
626 base::Unretained(resource_metadata_),
629 base::Bind(&FileSystem::ReadDirectoryAfterRead,
630 weak_ptr_factory_.GetWeakPtr(),
633 base::Owned(entries)));
636 void FileSystem::ReadDirectoryAfterRead(const base::FilePath& directory_path,
637 const ReadDirectoryCallback& callback,
638 const ResourceEntryVector* entries,
640 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
641 DCHECK(!callback.is_null());
643 if (error != FILE_ERROR_OK) {
644 callback.Run(error, scoped_ptr<ResourceEntryVector>(), false);
648 // TODO(satorux): Stop handling hide_hosted_docs here. crbug.com/256520.
649 const bool hide_hosted_docs =
650 pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles);
651 scoped_ptr<ResourceEntryVector> filtered(new ResourceEntryVector);
652 for (size_t i = 0; i < entries->size(); ++i) {
653 if (hide_hosted_docs &&
654 entries->at(i).file_specific_info().is_hosted_document()) {
657 filtered->push_back(entries->at(i));
660 callback.Run(FILE_ERROR_OK, filtered.Pass(), false);
663 void FileSystem::GetAvailableSpace(
664 const GetAvailableSpaceCallback& callback) {
665 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
666 DCHECK(!callback.is_null());
668 about_resource_loader_->GetAboutResource(
669 base::Bind(&FileSystem::OnGetAboutResource,
670 weak_ptr_factory_.GetWeakPtr(),
674 void FileSystem::OnGetAboutResource(
675 const GetAvailableSpaceCallback& callback,
676 google_apis::GDataErrorCode status,
677 scoped_ptr<google_apis::AboutResource> about_resource) {
678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
679 DCHECK(!callback.is_null());
681 FileError error = GDataToFileError(status);
682 if (error != FILE_ERROR_OK) {
683 callback.Run(error, -1, -1);
686 DCHECK(about_resource);
688 callback.Run(FILE_ERROR_OK,
689 about_resource->quota_bytes_total(),
690 about_resource->quota_bytes_used());
693 void FileSystem::GetShareUrl(
694 const base::FilePath& file_path,
695 const GURL& embed_origin,
696 const GetShareUrlCallback& callback) {
697 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
698 DCHECK(!callback.is_null());
700 // Resolve the resource id.
701 resource_metadata_->GetResourceEntryByPathOnUIThread(
703 base::Bind(&FileSystem::GetShareUrlAfterGetResourceEntry,
704 weak_ptr_factory_.GetWeakPtr(),
710 void FileSystem::GetShareUrlAfterGetResourceEntry(
711 const base::FilePath& file_path,
712 const GURL& embed_origin,
713 const GetShareUrlCallback& callback,
715 scoped_ptr<ResourceEntry> entry) {
716 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
717 DCHECK(!callback.is_null());
719 if (error != FILE_ERROR_OK) {
720 callback.Run(error, GURL());
723 if (entry->resource_id().empty()) {
724 // This entry does not exist on the server. Just return.
725 callback.Run(FILE_ERROR_FAILED, GURL());
729 scheduler_->GetShareUrl(
730 entry->resource_id(),
732 ClientContext(USER_INITIATED),
733 base::Bind(&FileSystem::OnGetResourceEntryForGetShareUrl,
734 weak_ptr_factory_.GetWeakPtr(),
738 void FileSystem::OnGetResourceEntryForGetShareUrl(
739 const GetShareUrlCallback& callback,
740 google_apis::GDataErrorCode status,
741 const GURL& share_url) {
742 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
743 DCHECK(!callback.is_null());
745 FileError error = GDataToFileError(status);
746 if (error != FILE_ERROR_OK) {
747 callback.Run(error, GURL());
751 if (share_url.is_empty()) {
752 callback.Run(FILE_ERROR_FAILED, GURL());
756 callback.Run(FILE_ERROR_OK, share_url);
759 void FileSystem::Search(const std::string& search_query,
760 const GURL& next_link,
761 const SearchCallback& callback) {
762 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
763 DCHECK(!callback.is_null());
764 search_operation_->Search(search_query, next_link, callback);
767 void FileSystem::SearchMetadata(const std::string& query,
769 int at_most_num_matches,
770 const SearchMetadataCallback& callback) {
771 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
773 // TODO(satorux): Stop handling hide_hosted_docs here. crbug.com/256520.
774 if (pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles))
775 options |= SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS;
777 drive::internal::SearchMetadata(blocking_task_runner_,
785 void FileSystem::OnDirectoryChangedByOperation(
786 const base::FilePath& directory_path) {
787 OnDirectoryChanged(directory_path);
790 void FileSystem::OnEntryUpdatedByOperation(const std::string& local_id) {
791 sync_client_->AddUpdateTask(ClientContext(USER_INITIATED), local_id);
794 void FileSystem::OnDriveSyncError(file_system::DriveSyncErrorType type,
795 const std::string& local_id) {
796 base::PostTaskAndReplyWithResult(
797 blocking_task_runner_,
799 base::Bind(&internal::ResourceMetadata::GetFilePath,
800 base::Unretained(resource_metadata_),
802 base::Bind(&FileSystem::OnDriveSyncErrorAfterGetFilePath,
803 weak_ptr_factory_.GetWeakPtr(),
807 void FileSystem::OnDriveSyncErrorAfterGetFilePath(
808 file_system::DriveSyncErrorType type,
809 const base::FilePath& path) {
812 FOR_EACH_OBSERVER(FileSystemObserver,
814 OnDriveSyncError(type, path));
817 void FileSystem::OnDirectoryChanged(const base::FilePath& directory_path) {
818 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
820 FOR_EACH_OBSERVER(FileSystemObserver, observers_,
821 OnDirectoryChanged(directory_path));
824 void FileSystem::OnLoadFromServerComplete() {
825 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
827 sync_client_->StartCheckingExistingPinnedFiles();
830 void FileSystem::OnInitialLoadComplete() {
831 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
833 blocking_task_runner_->PostTask(FROM_HERE,
834 base::Bind(&internal::RemoveStaleCacheFiles,
836 resource_metadata_));
837 sync_client_->StartProcessingBacklog();
840 void FileSystem::GetMetadata(
841 const GetFilesystemMetadataCallback& callback) {
842 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
843 DCHECK(!callback.is_null());
845 FileSystemMetadata metadata;
846 metadata.refreshing = change_list_loader_->IsRefreshing();
848 // Metadata related to delta update.
849 metadata.last_update_check_time = last_update_check_time_;
850 metadata.last_update_check_error = last_update_check_error_;
852 base::PostTaskAndReplyWithResult(
853 blocking_task_runner_,
855 base::Bind(&internal::ResourceMetadata::GetLargestChangestamp,
856 base::Unretained(resource_metadata_)),
857 base::Bind(&OnGetLargestChangestamp, metadata, callback));
860 void FileSystem::MarkCacheFileAsMounted(
861 const base::FilePath& drive_file_path,
862 const MarkMountedCallback& callback) {
863 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
864 DCHECK(!callback.is_null());
866 base::FilePath* cache_file_path = new base::FilePath;
867 base::PostTaskAndReplyWithResult(
868 blocking_task_runner_,
870 base::Bind(&MarkCacheFileAsMountedInternal,
875 base::Bind(&RunMarkMountedCallback,
877 base::Owned(cache_file_path)));
880 void FileSystem::MarkCacheFileAsUnmounted(
881 const base::FilePath& cache_file_path,
882 const FileOperationCallback& callback) {
883 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
884 DCHECK(!callback.is_null());
886 if (!cache_->IsUnderFileCacheDirectory(cache_file_path)) {
887 callback.Run(FILE_ERROR_FAILED);
891 base::PostTaskAndReplyWithResult(
892 blocking_task_runner_,
894 base::Bind(&internal::FileCache::MarkAsUnmounted,
895 base::Unretained(cache_),
900 void FileSystem::GetCacheEntry(
901 const base::FilePath& drive_file_path,
902 const GetCacheEntryCallback& callback) {
903 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
904 DCHECK(!callback.is_null());
906 FileCacheEntry* cache_entry = new FileCacheEntry;
907 base::PostTaskAndReplyWithResult(
908 blocking_task_runner_,
910 base::Bind(&GetCacheEntryInternal,
915 base::Bind(&RunGetCacheEntryCallback,
917 base::Owned(cache_entry)));
920 void FileSystem::OpenFile(const base::FilePath& file_path,
922 const std::string& mime_type,
923 const OpenFileCallback& callback) {
924 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
925 DCHECK(!callback.is_null());
927 open_file_operation_->OpenFile(file_path, open_mode, mime_type, callback);