OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/drive/file_system.h" | 5 #include "chrome/browser/chromeos/drive/file_system.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/message_loop/message_loop_proxy.h" | 9 #include "base/message_loop/message_loop_proxy.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 #include "content/public/browser/browser_thread.h" | 32 #include "content/public/browser/browser_thread.h" |
33 #include "content/public/browser/notification_details.h" | 33 #include "content/public/browser/notification_details.h" |
34 | 34 |
35 using content::BrowserThread; | 35 using content::BrowserThread; |
36 | 36 |
37 namespace drive { | 37 namespace drive { |
38 namespace { | 38 namespace { |
39 | 39 |
40 //================================ Helper functions ============================ | 40 //================================ Helper functions ============================ |
41 | 41 |
42 // Creates a temporary JSON file representing a document with |alternate_url| | |
43 // and |resource_id| under |document_dir| on blocking pool. | |
44 FileError CreateDocumentJsonFileOnBlockingPool( | |
45 const base::FilePath& document_dir, | |
46 const GURL& alternate_url, | |
47 const std::string& resource_id, | |
48 base::FilePath* temp_file_path) { | |
49 DCHECK(temp_file_path); | |
50 | |
51 if (!file_util::CreateTemporaryFileInDir(document_dir, temp_file_path) || | |
52 !util::CreateGDocFile(*temp_file_path, alternate_url, resource_id)) | |
53 return FILE_ERROR_FAILED; | |
54 return FILE_ERROR_OK; | |
55 } | |
56 | |
57 // Helper function for binding |path| to GetResourceEntryWithFilePathCallback | 42 // Helper function for binding |path| to GetResourceEntryWithFilePathCallback |
58 // and create GetResourceEntryCallback. | 43 // and create GetResourceEntryCallback. |
59 void RunGetResourceEntryWithFilePathCallback( | 44 void RunGetResourceEntryWithFilePathCallback( |
60 const GetResourceEntryWithFilePathCallback& callback, | 45 const GetResourceEntryWithFilePathCallback& callback, |
61 const base::FilePath& path, | 46 const base::FilePath& path, |
62 FileError error, | 47 FileError error, |
63 scoped_ptr<ResourceEntry> entry) { | 48 scoped_ptr<ResourceEntry> entry) { |
64 DCHECK(!callback.is_null()); | 49 DCHECK(!callback.is_null()); |
65 callback.Run(error, path, entry.Pass()); | 50 callback.Run(error, path, entry.Pass()); |
66 } | 51 } |
(...skipping 13 matching lines...) Expand all Loading... |
80 | 65 |
81 // Thin adapter to map GetFileCallback to FileOperationCallback. | 66 // Thin adapter to map GetFileCallback to FileOperationCallback. |
82 void GetFileCallbackToFileOperationCallbackAdapter( | 67 void GetFileCallbackToFileOperationCallbackAdapter( |
83 const FileOperationCallback& callback, | 68 const FileOperationCallback& callback, |
84 FileError error, | 69 FileError error, |
85 const base::FilePath& unused_file_path, | 70 const base::FilePath& unused_file_path, |
86 scoped_ptr<ResourceEntry> unused_entry) { | 71 scoped_ptr<ResourceEntry> unused_entry) { |
87 callback.Run(error); | 72 callback.Run(error); |
88 } | 73 } |
89 | 74 |
90 // Creates a file with unique name in |dir| and stores the path to |temp_file|. | |
91 // Additionally, sets the permission of the file to allow read access from | |
92 // others and group member users (i.e, "-rw-r--r--"). | |
93 // We need this wrapper because Drive cache files may be read from other | |
94 // processes (e.g., cros_disks for mounting zip files). | |
95 // | |
96 // Must be called on the blocking pool. | |
97 bool CreateTemporaryReadableFileInDir(const base::FilePath& dir, | |
98 base::FilePath* temp_file) { | |
99 if (!file_util::CreateTemporaryFileInDir(dir, temp_file)) | |
100 return false; | |
101 return file_util::SetPosixFilePermissions( | |
102 *temp_file, | |
103 file_util::FILE_PERMISSION_READ_BY_USER | | |
104 file_util::FILE_PERMISSION_WRITE_BY_USER | | |
105 file_util::FILE_PERMISSION_READ_BY_GROUP | | |
106 file_util::FILE_PERMISSION_READ_BY_OTHERS); | |
107 } | |
108 | |
109 } // namespace | 75 } // namespace |
110 | 76 |
111 // FileSystem::GetFileCompleteForOpenParams struct implementation. | |
112 struct FileSystem::GetFileCompleteForOpenParams { | |
113 GetFileCompleteForOpenParams(const OpenFileCallback& callback, | |
114 const std::string& resource_id, | |
115 const std::string& md5); | |
116 OpenFileCallback callback; | |
117 std::string resource_id; | |
118 std::string md5; | |
119 }; | |
120 | |
121 FileSystem::GetFileCompleteForOpenParams::GetFileCompleteForOpenParams( | |
122 const OpenFileCallback& callback, | |
123 const std::string& resource_id, | |
124 const std::string& md5) | |
125 : callback(callback), | |
126 resource_id(resource_id), | |
127 md5(md5) { | |
128 } | |
129 | |
130 // FileSystem::GetResolvedFileParams struct implementation. | |
131 struct FileSystem::GetResolvedFileParams { | |
132 GetResolvedFileParams( | |
133 const base::FilePath& drive_file_path, | |
134 const DriveClientContext& context, | |
135 scoped_ptr<ResourceEntry> entry, | |
136 const GetFileContentInitializedCallback& initialized_callback, | |
137 const GetFileCallback& get_file_callback, | |
138 const google_apis::GetContentCallback& get_content_callback) | |
139 : drive_file_path(drive_file_path), | |
140 context(context), | |
141 entry(entry.Pass()), | |
142 initialized_callback(initialized_callback), | |
143 get_file_callback(get_file_callback), | |
144 get_content_callback(get_content_callback) { | |
145 DCHECK(!get_file_callback.is_null()); | |
146 DCHECK(this->entry); | |
147 } | |
148 | |
149 void OnError(FileError error) { | |
150 get_file_callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>()); | |
151 } | |
152 | |
153 void OnCacheFileFound(const base::FilePath& local_file_path) { | |
154 if (initialized_callback.is_null()) { | |
155 return; | |
156 } | |
157 | |
158 scoped_ptr<ResourceEntry> new_entry(new ResourceEntry(*entry)); | |
159 initialized_callback.Run(FILE_ERROR_OK, | |
160 new_entry.Pass(), | |
161 local_file_path, | |
162 base::Closure()); | |
163 } | |
164 | |
165 void OnStartDownloading(const base::Closure& cancel_download_closure) { | |
166 if (initialized_callback.is_null()) { | |
167 return; | |
168 } | |
169 | |
170 scoped_ptr<ResourceEntry> new_entry(new ResourceEntry(*entry)); | |
171 initialized_callback.Run(FILE_ERROR_OK, | |
172 new_entry.Pass(), | |
173 base::FilePath(), | |
174 cancel_download_closure); | |
175 } | |
176 | |
177 void OnComplete(const base::FilePath& local_file_path) { | |
178 get_file_callback.Run(FILE_ERROR_OK, local_file_path, | |
179 scoped_ptr<ResourceEntry>(new ResourceEntry(*entry))); | |
180 } | |
181 | |
182 const base::FilePath drive_file_path; | |
183 const DriveClientContext context; | |
184 scoped_ptr<ResourceEntry> entry; | |
185 const GetFileContentInitializedCallback initialized_callback; | |
186 const GetFileCallback get_file_callback; | |
187 const google_apis::GetContentCallback get_content_callback; | |
188 }; | |
189 | |
190 FileSystem::FileSystem( | 77 FileSystem::FileSystem( |
191 Profile* profile, | 78 Profile* profile, |
192 internal::FileCache* cache, | 79 internal::FileCache* cache, |
193 google_apis::DriveServiceInterface* drive_service, | 80 google_apis::DriveServiceInterface* drive_service, |
194 JobScheduler* scheduler, | 81 JobScheduler* scheduler, |
195 internal::ResourceMetadata* resource_metadata, | 82 internal::ResourceMetadata* resource_metadata, |
196 base::SequencedTaskRunner* blocking_task_runner) | 83 base::SequencedTaskRunner* blocking_task_runner) |
197 : profile_(profile), | 84 : profile_(profile), |
198 cache_(cache), | 85 cache_(cache), |
199 drive_service_(drive_service), | 86 drive_service_(drive_service), |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 | 374 |
488 cache_->UnpinOnUIThread(entry->resource_id(), | 375 cache_->UnpinOnUIThread(entry->resource_id(), |
489 entry->file_specific_info().file_md5(), callback); | 376 entry->file_specific_info().file_md5(), callback); |
490 } | 377 } |
491 | 378 |
492 void FileSystem::GetFileByPath(const base::FilePath& file_path, | 379 void FileSystem::GetFileByPath(const base::FilePath& file_path, |
493 const GetFileCallback& callback) { | 380 const GetFileCallback& callback) { |
494 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
495 DCHECK(!callback.is_null()); | 382 DCHECK(!callback.is_null()); |
496 | 383 |
497 resource_metadata_->GetResourceEntryByPathOnUIThread( | 384 operations_.EnsureFileDownloaded( |
498 file_path, | 385 file_path, |
499 base::Bind(&FileSystem::OnGetResourceEntryCompleteForGetFileByPath, | 386 DriveClientContext(USER_INITIATED), |
500 weak_ptr_factory_.GetWeakPtr(), | 387 GetFileContentInitializedCallback(), |
501 file_path, | 388 google_apis::GetContentCallback(), |
502 callback)); | 389 callback); |
503 } | |
504 | |
505 void FileSystem::OnGetResourceEntryCompleteForGetFileByPath( | |
506 const base::FilePath& file_path, | |
507 const GetFileCallback& callback, | |
508 FileError error, | |
509 scoped_ptr<ResourceEntry> entry) { | |
510 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
511 DCHECK(!callback.is_null()); | |
512 | |
513 if (error != FILE_ERROR_OK) { | |
514 callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>()); | |
515 return; | |
516 } | |
517 DCHECK(entry); | |
518 | |
519 GetResolvedFileByPath( | |
520 make_scoped_ptr(new GetResolvedFileParams( | |
521 file_path, | |
522 DriveClientContext(USER_INITIATED), | |
523 entry.Pass(), | |
524 GetFileContentInitializedCallback(), | |
525 callback, | |
526 google_apis::GetContentCallback()))); | |
527 } | 390 } |
528 | 391 |
529 void FileSystem::GetFileByResourceId( | 392 void FileSystem::GetFileByResourceId( |
530 const std::string& resource_id, | 393 const std::string& resource_id, |
531 const DriveClientContext& context, | 394 const DriveClientContext& context, |
532 const GetFileCallback& get_file_callback, | 395 const GetFileCallback& get_file_callback, |
533 const google_apis::GetContentCallback& get_content_callback) { | 396 const google_apis::GetContentCallback& get_content_callback) { |
534 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
535 DCHECK(!resource_id.empty()); | 398 DCHECK(!resource_id.empty()); |
536 DCHECK(!get_file_callback.is_null()); | 399 DCHECK(!get_file_callback.is_null()); |
(...skipping 16 matching lines...) Expand all Loading... |
553 scoped_ptr<ResourceEntry> entry) { | 416 scoped_ptr<ResourceEntry> entry) { |
554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
555 DCHECK(!get_file_callback.is_null()); | 418 DCHECK(!get_file_callback.is_null()); |
556 | 419 |
557 if (error != FILE_ERROR_OK) { | 420 if (error != FILE_ERROR_OK) { |
558 get_file_callback.Run(FILE_ERROR_NOT_FOUND, base::FilePath(), | 421 get_file_callback.Run(FILE_ERROR_NOT_FOUND, base::FilePath(), |
559 scoped_ptr<ResourceEntry>()); | 422 scoped_ptr<ResourceEntry>()); |
560 return; | 423 return; |
561 } | 424 } |
562 | 425 |
563 GetResolvedFileByPath( | 426 operations_.EnsureFileDownloaded( |
564 make_scoped_ptr(new GetResolvedFileParams( | 427 file_path, |
565 file_path, | 428 context, |
566 context, | 429 GetFileContentInitializedCallback(), |
567 entry.Pass(), | 430 get_content_callback, |
568 GetFileContentInitializedCallback(), | 431 get_file_callback); |
569 get_file_callback, | |
570 get_content_callback))); | |
571 } | 432 } |
572 | 433 |
573 void FileSystem::GetFileContentByPath( | 434 void FileSystem::GetFileContentByPath( |
574 const base::FilePath& file_path, | 435 const base::FilePath& file_path, |
575 const GetFileContentInitializedCallback& initialized_callback, | 436 const GetFileContentInitializedCallback& initialized_callback, |
576 const google_apis::GetContentCallback& get_content_callback, | 437 const google_apis::GetContentCallback& get_content_callback, |
577 const FileOperationCallback& completion_callback) { | 438 const FileOperationCallback& completion_callback) { |
578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
579 DCHECK(!initialized_callback.is_null()); | 440 DCHECK(!initialized_callback.is_null()); |
580 DCHECK(!get_content_callback.is_null()); | 441 DCHECK(!get_content_callback.is_null()); |
581 DCHECK(!completion_callback.is_null()); | 442 DCHECK(!completion_callback.is_null()); |
582 | 443 |
583 resource_metadata_->GetResourceEntryByPathOnUIThread( | 444 operations_.EnsureFileDownloaded( |
584 file_path, | 445 file_path, |
585 base::Bind(&FileSystem::GetFileContentByPathAfterGetEntry, | 446 DriveClientContext(USER_INITIATED), |
586 weak_ptr_factory_.GetWeakPtr(), | 447 initialized_callback, |
587 file_path, | 448 get_content_callback, |
588 initialized_callback, | 449 base::Bind(&GetFileCallbackToFileOperationCallbackAdapter, |
589 get_content_callback, | |
590 completion_callback)); | 450 completion_callback)); |
591 } | 451 } |
592 | 452 |
593 void FileSystem::GetFileContentByPathAfterGetEntry( | |
594 const base::FilePath& file_path, | |
595 const GetFileContentInitializedCallback& initialized_callback, | |
596 const google_apis::GetContentCallback& get_content_callback, | |
597 const FileOperationCallback& completion_callback, | |
598 FileError error, | |
599 scoped_ptr<ResourceEntry> entry) { | |
600 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
601 DCHECK(!initialized_callback.is_null()); | |
602 DCHECK(!get_content_callback.is_null()); | |
603 DCHECK(!completion_callback.is_null()); | |
604 | |
605 if (error != FILE_ERROR_OK) { | |
606 completion_callback.Run(error); | |
607 return; | |
608 } | |
609 | |
610 DCHECK(entry); | |
611 GetResolvedFileByPath( | |
612 make_scoped_ptr(new GetResolvedFileParams( | |
613 file_path, | |
614 DriveClientContext(USER_INITIATED), | |
615 entry.Pass(), | |
616 initialized_callback, | |
617 base::Bind(&GetFileCallbackToFileOperationCallbackAdapter, | |
618 completion_callback), | |
619 get_content_callback))); | |
620 } | |
621 | |
622 void FileSystem::GetResourceEntryByPath( | 453 void FileSystem::GetResourceEntryByPath( |
623 const base::FilePath& file_path, | 454 const base::FilePath& file_path, |
624 const GetResourceEntryCallback& callback) { | 455 const GetResourceEntryCallback& callback) { |
625 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
626 DCHECK(!callback.is_null()); | 457 DCHECK(!callback.is_null()); |
627 | 458 |
628 // ResourceMetadata may know about the entry even if the resource | 459 // ResourceMetadata may know about the entry even if the resource |
629 // metadata is not yet fully loaded. For instance, ResourceMetadata() | 460 // metadata is not yet fully loaded. For instance, ResourceMetadata() |
630 // always knows about the root directory. For "fast fetch" | 461 // always knows about the root directory. For "fast fetch" |
631 // (crbug.com/178348) to work, it's needed to delay the resource metadata | 462 // (crbug.com/178348) to work, it's needed to delay the resource metadata |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 callback.Run(error, | 619 callback.Run(error, |
789 hide_hosted_docs_, | 620 hide_hosted_docs_, |
790 scoped_ptr<ResourceEntryVector>()); | 621 scoped_ptr<ResourceEntryVector>()); |
791 return; | 622 return; |
792 } | 623 } |
793 DCHECK(entries.get()); // This is valid for empty directories too. | 624 DCHECK(entries.get()); // This is valid for empty directories too. |
794 | 625 |
795 callback.Run(FILE_ERROR_OK, hide_hosted_docs_, entries.Pass()); | 626 callback.Run(FILE_ERROR_OK, hide_hosted_docs_, entries.Pass()); |
796 } | 627 } |
797 | 628 |
798 void FileSystem::GetResolvedFileByPath( | |
799 scoped_ptr<GetResolvedFileParams> params) { | |
800 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
801 DCHECK(params); | |
802 | |
803 if (params->entry->file_info().is_directory()) { | |
804 params->OnError(FILE_ERROR_NOT_A_FILE); | |
805 return; | |
806 } | |
807 | |
808 // The file's entry should have its file specific info. | |
809 DCHECK(params->entry->has_file_specific_info()); | |
810 | |
811 // For a hosted document, we create a special JSON file to represent the | |
812 // document instead of fetching the document content in one of the exported | |
813 // formats. The JSON file contains the edit URL and resource ID of the | |
814 // document. | |
815 if (params->entry->file_specific_info().is_hosted_document()) { | |
816 base::FilePath* temp_file_path = new base::FilePath; | |
817 ResourceEntry* entry_ptr = params->entry.get(); | |
818 base::PostTaskAndReplyWithResult( | |
819 blocking_task_runner_, | |
820 FROM_HERE, | |
821 base::Bind(&CreateDocumentJsonFileOnBlockingPool, | |
822 cache_->GetCacheDirectoryPath( | |
823 internal::FileCache::CACHE_TYPE_TMP_DOCUMENTS), | |
824 GURL(entry_ptr->file_specific_info().alternate_url()), | |
825 entry_ptr->resource_id(), | |
826 temp_file_path), | |
827 base::Bind( | |
828 &FileSystem::GetResolvedFileByPathAfterCreateDocumentJsonFile, | |
829 weak_ptr_factory_.GetWeakPtr(), | |
830 base::Passed(¶ms), | |
831 base::Owned(temp_file_path))); | |
832 return; | |
833 } | |
834 | |
835 // Returns absolute path of the file if it were cached or to be cached. | |
836 ResourceEntry* entry_ptr = params->entry.get(); | |
837 cache_->GetFileOnUIThread( | |
838 entry_ptr->resource_id(), | |
839 entry_ptr->file_specific_info().file_md5(), | |
840 base::Bind( | |
841 &FileSystem::GetResolvedFileByPathAfterGetFileFromCache, | |
842 weak_ptr_factory_.GetWeakPtr(), | |
843 base::Passed(¶ms))); | |
844 } | |
845 | |
846 void FileSystem::GetResolvedFileByPathAfterCreateDocumentJsonFile( | |
847 scoped_ptr<GetResolvedFileParams> params, | |
848 const base::FilePath* file_path, | |
849 FileError error) { | |
850 DCHECK(params); | |
851 DCHECK(file_path); | |
852 | |
853 if (error != FILE_ERROR_OK) { | |
854 params->OnError(error); | |
855 return; | |
856 } | |
857 | |
858 params->OnCacheFileFound(*file_path); | |
859 params->OnComplete(*file_path); | |
860 } | |
861 | |
862 void FileSystem::GetResolvedFileByPathAfterGetFileFromCache( | |
863 scoped_ptr<GetResolvedFileParams> params, | |
864 FileError error, | |
865 const base::FilePath& cache_file_path) { | |
866 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
867 DCHECK(params); | |
868 | |
869 // Have we found the file in cache? If so, return it back to the caller. | |
870 if (error == FILE_ERROR_OK) { | |
871 params->OnCacheFileFound(cache_file_path); | |
872 params->OnComplete(cache_file_path); | |
873 return; | |
874 } | |
875 | |
876 // If cache file is not found, try to download the file from the server | |
877 // instead. This logic is rather complicated but here's how this works: | |
878 // | |
879 // Retrieve fresh file metadata from server. We will extract file size and | |
880 // download url from there. Note that the download url is transient. | |
881 // | |
882 // Check if we have enough space, based on the expected file size. | |
883 // - if we don't have enough space, try to free up the disk space | |
884 // - if we still don't have enough space, return "no space" error | |
885 // - if we have enough space, start downloading the file from the server | |
886 GetResolvedFileParams* params_ptr = params.get(); | |
887 scheduler_->GetResourceEntry( | |
888 params_ptr->entry->resource_id(), | |
889 params_ptr->context, | |
890 base::Bind(&FileSystem::GetResolvedFileByPathAfterGetResourceEntry, | |
891 weak_ptr_factory_.GetWeakPtr(), | |
892 base::Passed(¶ms))); | |
893 } | |
894 | |
895 void FileSystem::GetResolvedFileByPathAfterGetResourceEntry( | |
896 scoped_ptr<GetResolvedFileParams> params, | |
897 google_apis::GDataErrorCode status, | |
898 scoped_ptr<google_apis::ResourceEntry> entry) { | |
899 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
900 DCHECK(params); | |
901 | |
902 const FileError error = util::GDataToFileError(status); | |
903 if (error != FILE_ERROR_OK) { | |
904 params->OnError(error); | |
905 return; | |
906 } | |
907 | |
908 // The download URL is: | |
909 // 1) src attribute of content element, on GData WAPI. | |
910 // 2) the value of the key 'downloadUrl', on Drive API v2. | |
911 // In both cases, we can use ResourceEntry::download_url(). | |
912 const GURL& download_url = entry->download_url(); | |
913 | |
914 // The download URL can be empty for non-downloadable files (such as files | |
915 // shared from others with "prevent downloading by viewers" flag set.) | |
916 if (download_url.is_empty()) { | |
917 params->OnError(FILE_ERROR_ACCESS_DENIED); | |
918 return; | |
919 } | |
920 | |
921 DCHECK_EQ(params->entry->resource_id(), entry->resource_id()); | |
922 resource_metadata_->RefreshEntryOnUIThread( | |
923 ConvertToResourceEntry(*entry), | |
924 base::Bind(&FileSystem::GetResolvedFileByPathAfterRefreshEntry, | |
925 weak_ptr_factory_.GetWeakPtr(), | |
926 base::Passed(¶ms), | |
927 download_url)); | |
928 } | |
929 | |
930 void FileSystem::GetResolvedFileByPathAfterRefreshEntry( | |
931 scoped_ptr<GetResolvedFileParams> params, | |
932 const GURL& download_url, | |
933 FileError error, | |
934 const base::FilePath& drive_file_path, | |
935 scoped_ptr<ResourceEntry> entry) { | |
936 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
937 DCHECK(params); | |
938 | |
939 if (error != FILE_ERROR_OK) { | |
940 params->OnError(error); | |
941 return; | |
942 } | |
943 | |
944 int64 file_size = entry->file_info().size(); | |
945 params->entry = entry.Pass(); // Update the entry in |params|. | |
946 cache_->FreeDiskSpaceIfNeededForOnUIThread( | |
947 file_size, | |
948 base::Bind(&FileSystem::GetResolvedFileByPathAfterFreeDiskSpace, | |
949 weak_ptr_factory_.GetWeakPtr(), | |
950 base::Passed(¶ms), | |
951 download_url)); | |
952 } | |
953 | |
954 void FileSystem::GetResolvedFileByPathAfterFreeDiskSpace( | |
955 scoped_ptr<GetResolvedFileParams> params, | |
956 const GURL& download_url, | |
957 bool has_enough_space) { | |
958 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
959 DCHECK(params); | |
960 | |
961 if (!has_enough_space) { | |
962 // If no enough space, return FILE_ERROR_NO_SPACE. | |
963 params->OnError(FILE_ERROR_NO_SPACE); | |
964 return; | |
965 } | |
966 | |
967 // We have enough disk space. Create download destination file. | |
968 const base::FilePath temp_download_directory = cache_->GetCacheDirectoryPath( | |
969 internal::FileCache::CACHE_TYPE_TMP_DOWNLOADS); | |
970 base::FilePath* file_path = new base::FilePath; | |
971 base::PostTaskAndReplyWithResult( | |
972 blocking_task_runner_, | |
973 FROM_HERE, | |
974 base::Bind(&CreateTemporaryReadableFileInDir, | |
975 temp_download_directory, | |
976 file_path), | |
977 base::Bind(&FileSystem::GetResolveFileByPathAfterCreateTemporaryFile, | |
978 weak_ptr_factory_.GetWeakPtr(), | |
979 base::Passed(¶ms), | |
980 download_url, | |
981 base::Owned(file_path))); | |
982 } | |
983 | |
984 void FileSystem::GetResolveFileByPathAfterCreateTemporaryFile( | |
985 scoped_ptr<GetResolvedFileParams> params, | |
986 const GURL& download_url, | |
987 base::FilePath* temp_file, | |
988 bool success) { | |
989 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
990 DCHECK(params); | |
991 | |
992 if (!success) { | |
993 params->OnError(FILE_ERROR_FAILED); | |
994 return; | |
995 } | |
996 | |
997 GetResolvedFileParams* params_ptr = params.get(); | |
998 JobID id = scheduler_->DownloadFile( | |
999 params_ptr->drive_file_path, | |
1000 *temp_file, | |
1001 download_url, | |
1002 params_ptr->context, | |
1003 base::Bind(&FileSystem::GetResolvedFileByPathAfterDownloadFile, | |
1004 weak_ptr_factory_.GetWeakPtr(), | |
1005 base::Passed(¶ms)), | |
1006 params_ptr->get_content_callback); | |
1007 params_ptr->OnStartDownloading( | |
1008 base::Bind(&FileSystem::CancelJobInScheduler, | |
1009 weak_ptr_factory_.GetWeakPtr(), | |
1010 id)); | |
1011 } | |
1012 | |
1013 void FileSystem::GetResolvedFileByPathAfterDownloadFile( | |
1014 scoped_ptr<GetResolvedFileParams> params, | |
1015 google_apis::GDataErrorCode status, | |
1016 const base::FilePath& downloaded_file_path) { | |
1017 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1018 DCHECK(params); | |
1019 | |
1020 // If user cancels download of a pinned-but-not-fetched file, mark file as | |
1021 // unpinned so that we do not sync the file again. | |
1022 if (status == google_apis::GDATA_CANCELLED) { | |
1023 cache_->GetCacheEntryOnUIThread( | |
1024 params->entry->resource_id(), | |
1025 params->entry->file_specific_info().file_md5(), | |
1026 base::Bind( | |
1027 &FileSystem::GetResolvedFileByPathAfterGetCacheEntryForCancel, | |
1028 weak_ptr_factory_.GetWeakPtr(), | |
1029 params->entry->resource_id(), | |
1030 params->entry->file_specific_info().file_md5())); | |
1031 } | |
1032 | |
1033 FileError error = util::GDataToFileError(status); | |
1034 if (error != FILE_ERROR_OK) { | |
1035 params->OnError(error); | |
1036 return; | |
1037 } | |
1038 | |
1039 ResourceEntry* entry = params->entry.get(); | |
1040 cache_->StoreOnUIThread( | |
1041 entry->resource_id(), | |
1042 entry->file_specific_info().file_md5(), | |
1043 downloaded_file_path, | |
1044 internal::FileCache::FILE_OPERATION_MOVE, | |
1045 base::Bind(&FileSystem::GetResolvedFileByPathAfterStore, | |
1046 weak_ptr_factory_.GetWeakPtr(), | |
1047 base::Passed(¶ms), | |
1048 downloaded_file_path)); | |
1049 } | |
1050 | |
1051 void FileSystem::GetResolvedFileByPathAfterGetCacheEntryForCancel( | |
1052 const std::string& resource_id, | |
1053 const std::string& md5, | |
1054 bool success, | |
1055 const FileCacheEntry& cache_entry) { | |
1056 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1057 // TODO(hshi): http://crbug.com/127138 notify when file properties change. | |
1058 // This allows file manager to clear the "Available offline" checkbox. | |
1059 if (success && cache_entry.is_pinned()) { | |
1060 cache_->UnpinOnUIThread(resource_id, | |
1061 md5, | |
1062 base::Bind(&util::EmptyFileOperationCallback)); | |
1063 } | |
1064 } | |
1065 | |
1066 void FileSystem::GetResolvedFileByPathAfterStore( | |
1067 scoped_ptr<GetResolvedFileParams> params, | |
1068 const base::FilePath& downloaded_file_path, | |
1069 FileError error) { | |
1070 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1071 DCHECK(params); | |
1072 | |
1073 if (error != FILE_ERROR_OK) { | |
1074 blocking_task_runner_->PostTask( | |
1075 FROM_HERE, | |
1076 base::Bind(base::IgnoreResult(&file_util::Delete), | |
1077 downloaded_file_path, | |
1078 false /* recursive*/)); | |
1079 params->OnError(error); | |
1080 return; | |
1081 } | |
1082 // Storing to cache changes the "offline available" status, hence notify. | |
1083 OnDirectoryChanged(params->drive_file_path.DirName()); | |
1084 | |
1085 ResourceEntry* entry = params->entry.get(); | |
1086 cache_->GetFileOnUIThread( | |
1087 entry->resource_id(), | |
1088 entry->file_specific_info().file_md5(), | |
1089 base::Bind(&FileSystem::GetResolvedFileByPathAfterGetFile, | |
1090 weak_ptr_factory_.GetWeakPtr(), | |
1091 base::Passed(¶ms))); | |
1092 } | |
1093 | |
1094 void FileSystem::GetResolvedFileByPathAfterGetFile( | |
1095 scoped_ptr<GetResolvedFileParams> params, | |
1096 FileError error, | |
1097 const base::FilePath& cache_file) { | |
1098 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1099 DCHECK(params); | |
1100 | |
1101 if (error != FILE_ERROR_OK) { | |
1102 params->OnError(error); | |
1103 return; | |
1104 } | |
1105 params->OnComplete(cache_file); | |
1106 } | |
1107 | |
1108 void FileSystem::RefreshDirectory( | 629 void FileSystem::RefreshDirectory( |
1109 const base::FilePath& directory_path, | 630 const base::FilePath& directory_path, |
1110 const FileOperationCallback& callback) { | 631 const FileOperationCallback& callback) { |
1111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 632 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1112 DCHECK(!callback.is_null()); | 633 DCHECK(!callback.is_null()); |
1113 | 634 |
1114 // Make sure the destination directory exists. | 635 // Make sure the destination directory exists. |
1115 resource_metadata_->GetResourceEntryByPathOnUIThread( | 636 resource_metadata_->GetResourceEntryByPathOnUIThread( |
1116 directory_path, | 637 directory_path, |
1117 base::Bind(&FileSystem::RefreshDirectoryAfterGetResourceEntry, | 638 base::Bind(&FileSystem::RefreshDirectoryAfterGetResourceEntry, |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1360 // Open->Open->modify->Close->modify->Close; the second modify may not be | 881 // Open->Open->modify->Close->modify->Close; the second modify may not be |
1361 // synchronized to the server since it is already Closed on the cache). | 882 // synchronized to the server since it is already Closed on the cache). |
1362 if (open_files_.find(file_path) != open_files_.end()) { | 883 if (open_files_.find(file_path) != open_files_.end()) { |
1363 base::MessageLoopProxy::current()->PostTask( | 884 base::MessageLoopProxy::current()->PostTask( |
1364 FROM_HERE, | 885 FROM_HERE, |
1365 base::Bind(callback, FILE_ERROR_IN_USE, base::FilePath())); | 886 base::Bind(callback, FILE_ERROR_IN_USE, base::FilePath())); |
1366 return; | 887 return; |
1367 } | 888 } |
1368 open_files_.insert(file_path); | 889 open_files_.insert(file_path); |
1369 | 890 |
1370 resource_metadata_->GetResourceEntryByPathOnUIThread( | 891 operations_.EnsureFileDownloaded( |
1371 file_path, | 892 file_path, |
1372 base::Bind(&FileSystem::OnGetResourceEntryCompleteForOpenFile, | 893 DriveClientContext(USER_INITIATED), |
| 894 GetFileContentInitializedCallback(), |
| 895 google_apis::GetContentCallback(), |
| 896 base::Bind(&FileSystem::OpenFileAfterFileDownloaded, |
1373 weak_ptr_factory_.GetWeakPtr(), | 897 weak_ptr_factory_.GetWeakPtr(), |
1374 file_path, | 898 file_path, |
1375 base::Bind(&FileSystem::OnOpenFileFinished, | 899 base::Bind(&FileSystem::OnOpenFileFinished, |
1376 weak_ptr_factory_.GetWeakPtr(), | 900 weak_ptr_factory_.GetWeakPtr(), |
1377 file_path, | 901 file_path, |
1378 callback))); | 902 callback))); |
1379 } | 903 } |
1380 | 904 |
1381 void FileSystem::OnGetResourceEntryCompleteForOpenFile( | 905 void FileSystem::OpenFileAfterFileDownloaded( |
1382 const base::FilePath& file_path, | 906 const base::FilePath& file_path, |
1383 const OpenFileCallback& callback, | 907 const OpenFileCallback& callback, |
1384 FileError error, | 908 FileError error, |
| 909 const base::FilePath& local_file_path, |
1385 scoped_ptr<ResourceEntry> entry) { | 910 scoped_ptr<ResourceEntry> entry) { |
1386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 911 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1387 DCHECK(!callback.is_null()); | 912 DCHECK(!callback.is_null()); |
1388 DCHECK(entry.get() || error != FILE_ERROR_OK); | |
1389 | |
1390 if (entry.get() && !entry->has_file_specific_info()) | |
1391 error = FILE_ERROR_NOT_FOUND; | |
1392 | 913 |
1393 if (error == FILE_ERROR_OK) { | 914 if (error == FILE_ERROR_OK) { |
1394 if (entry->file_specific_info().file_md5().empty() || | 915 DCHECK(entry); |
1395 entry->file_specific_info().is_hosted_document()) { | 916 DCHECK(entry->has_file_specific_info()); |
1396 // No support for opening a directory or hosted document. | 917 if (entry->file_specific_info().is_hosted_document()) |
| 918 // No support for opening a hosted document. |
1397 error = FILE_ERROR_INVALID_OPERATION; | 919 error = FILE_ERROR_INVALID_OPERATION; |
1398 } | |
1399 } | 920 } |
1400 | 921 |
1401 if (error != FILE_ERROR_OK) { | 922 if (error != FILE_ERROR_OK) { |
1402 callback.Run(error, base::FilePath()); | 923 callback.Run(error, base::FilePath()); |
1403 return; | 924 return; |
1404 } | 925 } |
1405 | 926 |
1406 DCHECK(!entry->resource_id().empty()); | 927 cache_->MarkDirtyOnUIThread( |
1407 // Extract a pointer before we call Pass() so we can use it below. | 928 entry->resource_id(), |
1408 ResourceEntry* entry_ptr = entry.get(); | 929 entry->file_specific_info().file_md5(), |
1409 GetResolvedFileByPath( | 930 base::Bind(&FileSystem::OpenFileAfterMarkDirty, |
1410 make_scoped_ptr(new GetResolvedFileParams( | 931 weak_ptr_factory_.GetWeakPtr(), |
1411 file_path, | 932 entry->resource_id(), |
1412 DriveClientContext(USER_INITIATED), | 933 entry->file_specific_info().file_md5(), |
1413 entry.Pass(), | 934 callback)); |
1414 GetFileContentInitializedCallback(), | |
1415 base::Bind(&FileSystem::OnGetFileCompleteForOpenFile, | |
1416 weak_ptr_factory_.GetWeakPtr(), | |
1417 GetFileCompleteForOpenParams( | |
1418 callback, | |
1419 entry_ptr->resource_id(), | |
1420 entry_ptr->file_specific_info().file_md5())), | |
1421 google_apis::GetContentCallback()))); | |
1422 } | 935 } |
1423 | 936 |
1424 void FileSystem::OnGetFileCompleteForOpenFile( | 937 void FileSystem::OpenFileAfterMarkDirty( |
1425 const GetFileCompleteForOpenParams& params, | 938 const std::string& resource_id, |
1426 FileError error, | 939 const std::string& md5, |
1427 const base::FilePath& file_path, | 940 const OpenFileCallback& callback, |
1428 scoped_ptr<ResourceEntry> entry) { | 941 FileError error) { |
1429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 942 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1430 DCHECK(!params.callback.is_null()); | 943 DCHECK(!callback.is_null()); |
1431 | 944 |
1432 if (error != FILE_ERROR_OK) { | 945 if (error != FILE_ERROR_OK) { |
1433 params.callback.Run(error, base::FilePath()); | 946 callback.Run(error, base::FilePath()); |
1434 return; | 947 return; |
1435 } | 948 } |
1436 | 949 |
1437 // OpenFile ensures that the file is a regular file. | 950 cache_->GetFileOnUIThread(resource_id, md5, callback); |
1438 DCHECK(entry && !entry->file_specific_info().is_hosted_document()); | |
1439 | |
1440 cache_->MarkDirtyOnUIThread( | |
1441 params.resource_id, | |
1442 params.md5, | |
1443 base::Bind(&FileSystem::OnMarkDirtyInCacheCompleteForOpenFile, | |
1444 weak_ptr_factory_.GetWeakPtr(), | |
1445 params)); | |
1446 } | |
1447 | |
1448 void FileSystem::OnMarkDirtyInCacheCompleteForOpenFile( | |
1449 const GetFileCompleteForOpenParams& params, | |
1450 FileError error) { | |
1451 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1452 DCHECK(!params.callback.is_null()); | |
1453 | |
1454 if (error != FILE_ERROR_OK) { | |
1455 params.callback.Run(error, base::FilePath()); | |
1456 return; | |
1457 } | |
1458 | |
1459 cache_->GetFileOnUIThread(params.resource_id, params.md5, params.callback); | |
1460 } | 951 } |
1461 | 952 |
1462 void FileSystem::OnOpenFileFinished( | 953 void FileSystem::OnOpenFileFinished( |
1463 const base::FilePath& file_path, | 954 const base::FilePath& file_path, |
1464 const OpenFileCallback& callback, | 955 const OpenFileCallback& callback, |
1465 FileError result, | 956 FileError result, |
1466 const base::FilePath& cache_file_path) { | 957 const base::FilePath& cache_file_path) { |
1467 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 958 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1468 DCHECK(!callback.is_null()); | 959 DCHECK(!callback.is_null()); |
1469 | 960 |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1640 callback.Run(FILE_ERROR_NOT_FOUND, scoped_ptr<ResourceEntry>()); | 1131 callback.Run(FILE_ERROR_NOT_FOUND, scoped_ptr<ResourceEntry>()); |
1641 return; | 1132 return; |
1642 } | 1133 } |
1643 | 1134 |
1644 PlatformFileInfoProto entry_file_info; | 1135 PlatformFileInfoProto entry_file_info; |
1645 util::ConvertPlatformFileInfoToResourceEntry(*file_info, &entry_file_info); | 1136 util::ConvertPlatformFileInfoToResourceEntry(*file_info, &entry_file_info); |
1646 *entry->mutable_file_info() = entry_file_info; | 1137 *entry->mutable_file_info() = entry_file_info; |
1647 callback.Run(FILE_ERROR_OK, entry.Pass()); | 1138 callback.Run(FILE_ERROR_OK, entry.Pass()); |
1648 } | 1139 } |
1649 | 1140 |
1650 void FileSystem::CancelJobInScheduler(JobID id) { | |
1651 scheduler_->CancelJob(id); | |
1652 } | |
1653 | |
1654 } // namespace drive | 1141 } // namespace drive |
OLD | NEW |