Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1035)

Side by Side Diff: chrome/browser/chromeos/drive/file_system.cc

Issue 15681009: Extract GetResolveFile into DownloadOperation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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 drive_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
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 drive_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 drive_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
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(&params),
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(&params)));
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(&params)));
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(&params),
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(&params),
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(&params),
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(&params)),
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(&params),
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(&params)));
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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1378 // Open->Open->modify->Close->modify->Close; the second modify may not be 899 // Open->Open->modify->Close->modify->Close; the second modify may not be
1379 // synchronized to the server since it is already Closed on the cache). 900 // synchronized to the server since it is already Closed on the cache).
1380 if (open_files_.find(file_path) != open_files_.end()) { 901 if (open_files_.find(file_path) != open_files_.end()) {
1381 base::MessageLoopProxy::current()->PostTask( 902 base::MessageLoopProxy::current()->PostTask(
1382 FROM_HERE, 903 FROM_HERE,
1383 base::Bind(callback, FILE_ERROR_IN_USE, base::FilePath())); 904 base::Bind(callback, FILE_ERROR_IN_USE, base::FilePath()));
1384 return; 905 return;
1385 } 906 }
1386 open_files_.insert(file_path); 907 open_files_.insert(file_path);
1387 908
1388 resource_metadata_->GetResourceEntryByPathOnUIThread( 909 drive_operations_.EnsureFileDownloaded(
1389 file_path, 910 file_path,
1390 base::Bind(&FileSystem::OnGetResourceEntryCompleteForOpenFile, 911 DriveClientContext(USER_INITIATED),
912 GetFileContentInitializedCallback(),
913 google_apis::GetContentCallback(),
914 base::Bind(&FileSystem::OpenFileAfterFileDownloaded,
1391 weak_ptr_factory_.GetWeakPtr(), 915 weak_ptr_factory_.GetWeakPtr(),
1392 file_path, 916 file_path,
1393 base::Bind(&FileSystem::OnOpenFileFinished, 917 base::Bind(&FileSystem::OnOpenFileFinished,
1394 weak_ptr_factory_.GetWeakPtr(), 918 weak_ptr_factory_.GetWeakPtr(),
1395 file_path, 919 file_path,
1396 callback))); 920 callback)));
1397 } 921 }
1398 922
1399 void FileSystem::OnGetResourceEntryCompleteForOpenFile( 923 void FileSystem::OpenFileAfterFileDownloaded(
1400 const base::FilePath& file_path, 924 const base::FilePath& file_path,
1401 const OpenFileCallback& callback, 925 const OpenFileCallback& callback,
1402 FileError error, 926 FileError error,
927 const base::FilePath& local_file_path,
1403 scoped_ptr<ResourceEntry> entry) { 928 scoped_ptr<ResourceEntry> entry) {
1404 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 929 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1405 DCHECK(!callback.is_null()); 930 DCHECK(!callback.is_null());
1406 DCHECK(entry.get() || error != FILE_ERROR_OK);
1407
1408 if (entry.get() && !entry->has_file_specific_info())
1409 error = FILE_ERROR_NOT_FOUND;
1410 931
1411 if (error == FILE_ERROR_OK) { 932 if (error == FILE_ERROR_OK) {
1412 if (entry->file_specific_info().file_md5().empty() || 933 DCHECK(entry);
1413 entry->file_specific_info().is_hosted_document()) { 934 DCHECK(entry->has_file_specific_info());
1414 // No support for opening a directory or hosted document. 935 if (entry->file_specific_info().is_hosted_document())
936 // No support for opening a hosted document.
1415 error = FILE_ERROR_INVALID_OPERATION; 937 error = FILE_ERROR_INVALID_OPERATION;
1416 }
1417 } 938 }
1418 939
1419 if (error != FILE_ERROR_OK) { 940 if (error != FILE_ERROR_OK) {
1420 callback.Run(error, base::FilePath()); 941 callback.Run(error, base::FilePath());
1421 return; 942 return;
1422 } 943 }
1423 944
1424 DCHECK(!entry->resource_id().empty()); 945 cache_->MarkDirtyOnUIThread(
1425 // Extract a pointer before we call Pass() so we can use it below. 946 entry->resource_id(),
1426 ResourceEntry* entry_ptr = entry.get(); 947 entry->file_specific_info().file_md5(),
1427 GetResolvedFileByPath( 948 base::Bind(&FileSystem::OpenFileAfterMarkDirty,
1428 make_scoped_ptr(new GetResolvedFileParams( 949 weak_ptr_factory_.GetWeakPtr(),
1429 file_path, 950 entry->resource_id(),
1430 DriveClientContext(USER_INITIATED), 951 entry->file_specific_info().file_md5(),
1431 entry.Pass(), 952 callback));
1432 GetFileContentInitializedCallback(),
1433 base::Bind(&FileSystem::OnGetFileCompleteForOpenFile,
1434 weak_ptr_factory_.GetWeakPtr(),
1435 GetFileCompleteForOpenParams(
1436 callback,
1437 entry_ptr->resource_id(),
1438 entry_ptr->file_specific_info().file_md5())),
1439 google_apis::GetContentCallback())));
1440 } 953 }
1441 954
1442 void FileSystem::OnGetFileCompleteForOpenFile( 955 void FileSystem::OpenFileAfterMarkDirty(
1443 const GetFileCompleteForOpenParams& params, 956 const std::string& resource_id,
1444 FileError error, 957 const std::string& md5,
1445 const base::FilePath& file_path, 958 const OpenFileCallback& callback,
1446 scoped_ptr<ResourceEntry> entry) { 959 FileError error) {
1447 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 960 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1448 DCHECK(!params.callback.is_null()); 961 DCHECK(!callback.is_null());
1449 962
1450 if (error != FILE_ERROR_OK) { 963 if (error != FILE_ERROR_OK) {
1451 params.callback.Run(error, base::FilePath()); 964 callback.Run(error, base::FilePath());
1452 return; 965 return;
1453 } 966 }
1454 967
1455 // OpenFile ensures that the file is a regular file. 968 cache_->GetFileOnUIThread(resource_id, md5, callback);
1456 DCHECK(entry && !entry->file_specific_info().is_hosted_document());
1457
1458 cache_->MarkDirtyOnUIThread(
1459 params.resource_id,
1460 params.md5,
1461 base::Bind(&FileSystem::OnMarkDirtyInCacheCompleteForOpenFile,
1462 weak_ptr_factory_.GetWeakPtr(),
1463 params));
1464 }
1465
1466 void FileSystem::OnMarkDirtyInCacheCompleteForOpenFile(
1467 const GetFileCompleteForOpenParams& params,
1468 FileError error) {
1469 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1470 DCHECK(!params.callback.is_null());
1471
1472 if (error != FILE_ERROR_OK) {
1473 params.callback.Run(error, base::FilePath());
1474 return;
1475 }
1476
1477 cache_->GetFileOnUIThread(params.resource_id, params.md5, params.callback);
1478 } 969 }
1479 970
1480 void FileSystem::OnOpenFileFinished( 971 void FileSystem::OnOpenFileFinished(
1481 const base::FilePath& file_path, 972 const base::FilePath& file_path,
1482 const OpenFileCallback& callback, 973 const OpenFileCallback& callback,
1483 FileError result, 974 FileError result,
1484 const base::FilePath& cache_file_path) { 975 const base::FilePath& cache_file_path) {
1485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 976 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1486 DCHECK(!callback.is_null()); 977 DCHECK(!callback.is_null());
1487 978
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
1658 callback.Run(FILE_ERROR_NOT_FOUND, scoped_ptr<ResourceEntry>()); 1149 callback.Run(FILE_ERROR_NOT_FOUND, scoped_ptr<ResourceEntry>());
1659 return; 1150 return;
1660 } 1151 }
1661 1152
1662 PlatformFileInfoProto entry_file_info; 1153 PlatformFileInfoProto entry_file_info;
1663 util::ConvertPlatformFileInfoToResourceEntry(*file_info, &entry_file_info); 1154 util::ConvertPlatformFileInfoToResourceEntry(*file_info, &entry_file_info);
1664 *entry->mutable_file_info() = entry_file_info; 1155 *entry->mutable_file_info() = entry_file_info;
1665 callback.Run(FILE_ERROR_OK, entry.Pass()); 1156 callback.Run(FILE_ERROR_OK, entry.Pass());
1666 } 1157 }
1667 1158
1668 void FileSystem::CancelJobInScheduler(JobID id) { 1159 void FileSystem::CancelJobInScheduler(JobID id) {
kinaba 2013/05/24 09:10:23 You can remove this method. This is used only for
hidehiko 2013/05/26 15:39:36 Done.
1669 scheduler_->CancelJob(id); 1160 scheduler_->CancelJob(id);
1670 } 1161 }
1671 1162
1672 } // namespace drive 1163 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698