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

Side by Side Diff: chrome/browser/sync_file_system/drive_file_sync_service.cc

Issue 14977008: [SyncFileSystem] Separate out ApplyLocalChange from DriveFileSyncService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix local_win case 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/sync_file_system/drive_file_sync_service.h" 5 #include "chrome/browser/sync_file_system/drive_file_sync_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/memory/weak_ptr.h" 14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop/message_loop_proxy.h" 15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/utf_string_conversions.h" 16 #include "base/utf_string_conversions.h"
17 #include "base/values.h" 17 #include "base/values.h"
18 #include "chrome/browser/extensions/extension_service.h" 18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_system.h" 19 #include "chrome/browser/extensions/extension_system.h"
20 #include "chrome/browser/google_apis/drive_notification_manager.h" 20 #include "chrome/browser/google_apis/drive_notification_manager.h"
21 #include "chrome/browser/google_apis/drive_notification_manager_factory.h" 21 #include "chrome/browser/google_apis/drive_notification_manager_factory.h"
22 #include "chrome/browser/profiles/profile.h" 22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/sync_file_system/conflict_resolution_policy.h" 23 #include "chrome/browser/sync_file_system/conflict_resolution_policy.h"
24 #include "chrome/browser/sync_file_system/drive/api_util.h" 24 #include "chrome/browser/sync_file_system/drive/api_util.h"
25 #include "chrome/browser/sync_file_system/drive/local_change_processor_delegate. h"
25 #include "chrome/browser/sync_file_system/drive_file_sync_task_manager.h" 26 #include "chrome/browser/sync_file_system/drive_file_sync_task_manager.h"
26 #include "chrome/browser/sync_file_system/drive_file_sync_util.h" 27 #include "chrome/browser/sync_file_system/drive_file_sync_util.h"
27 #include "chrome/browser/sync_file_system/drive_metadata_store.h" 28 #include "chrome/browser/sync_file_system/drive_metadata_store.h"
28 #include "chrome/browser/sync_file_system/file_status_observer.h" 29 #include "chrome/browser/sync_file_system/file_status_observer.h"
29 #include "chrome/browser/sync_file_system/remote_change_handler.h" 30 #include "chrome/browser/sync_file_system/remote_change_handler.h"
30 #include "chrome/browser/sync_file_system/remote_change_processor.h" 31 #include "chrome/browser/sync_file_system/remote_change_processor.h"
31 #include "chrome/browser/sync_file_system/remote_sync_operation_resolver.h" 32 #include "chrome/browser/sync_file_system/remote_sync_operation_resolver.h"
32 #include "chrome/browser/sync_file_system/sync_file_system.pb.h" 33 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
33 #include "chrome/common/extensions/extension.h" 34 #include "chrome/common/extensions/extension.h"
34 #include "content/public/browser/browser_thread.h" 35 #include "content/public/browser/browser_thread.h"
35 #include "extensions/common/constants.h" 36 #include "extensions/common/constants.h"
36 #include "webkit/blob/scoped_file.h" 37 #include "webkit/blob/scoped_file.h"
37 #include "webkit/fileapi/file_system_url.h" 38 #include "webkit/fileapi/file_system_url.h"
38 #include "webkit/fileapi/file_system_util.h" 39 #include "webkit/fileapi/file_system_util.h"
39 #include "webkit/fileapi/syncable/sync_file_metadata.h" 40 #include "webkit/fileapi/syncable/sync_file_metadata.h"
40 #include "webkit/fileapi/syncable/sync_file_type.h" 41 #include "webkit/fileapi/syncable/sync_file_type.h"
41 #include "webkit/fileapi/syncable/syncable_file_system_util.h" 42 #include "webkit/fileapi/syncable/syncable_file_system_util.h"
42 43
43 using fileapi::FileSystemURL; 44 using fileapi::FileSystemURL;
44 45
45 namespace sync_file_system { 46 namespace sync_file_system {
46 47
48 typedef DriveFileSyncService::ConflictResolutionResult ConflictResolutionResult;
49
47 namespace { 50 namespace {
48 51
49 const base::FilePath::CharType kTempDirName[] = FILE_PATH_LITERAL("tmp"); 52 const base::FilePath::CharType kTempDirName[] = FILE_PATH_LITERAL("tmp");
50 const base::FilePath::CharType kSyncFileSystemDir[] = 53 const base::FilePath::CharType kSyncFileSystemDir[] =
51 FILE_PATH_LITERAL("Sync FileSystem"); 54 FILE_PATH_LITERAL("Sync FileSystem");
52 const base::FilePath::CharType kSyncFileSystemDirDev[] = 55 const base::FilePath::CharType kSyncFileSystemDirDev[] =
53 FILE_PATH_LITERAL("Sync FileSystem Dev"); 56 FILE_PATH_LITERAL("Sync FileSystem Dev");
54 57
55 const base::FilePath::CharType* GetSyncFileSystemDir() { 58 const base::FilePath::CharType* GetSyncFileSystemDir() {
56 return IsSyncDirectoryOperationEnabled() 59 return IsSyncDirectoryOperationEnabled()
57 ? kSyncFileSystemDirDev : kSyncFileSystemDir; 60 ? kSyncFileSystemDirDev : kSyncFileSystemDir;
58 } 61 }
59 62
60 bool CreateTemporaryFile(const base::FilePath& dir_path, 63 bool CreateTemporaryFile(const base::FilePath& dir_path,
61 webkit_blob::ScopedFile* temp_file) { 64 webkit_blob::ScopedFile* temp_file) {
62 base::FilePath temp_file_path; 65 base::FilePath temp_file_path;
63 const bool success = file_util::CreateDirectory(dir_path) && 66 const bool success = file_util::CreateDirectory(dir_path) &&
64 file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path); 67 file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path);
65 if (!success) 68 if (!success)
66 return success; 69 return success;
67 *temp_file = webkit_blob::ScopedFile( 70 *temp_file = webkit_blob::ScopedFile(
68 temp_file_path, 71 temp_file_path,
69 webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT, 72 webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
70 base::MessageLoopProxy::current()); 73 base::MessageLoopProxy::current());
71 return success; 74 return success;
72 } 75 }
73 76
74 void EmptyStatusCallback(SyncStatusCode status) {} 77 void EmptyStatusCallback(SyncStatusCode status) {}
75 78
76 std::string PathToTitle(const base::FilePath& path) {
77 if (!IsSyncDirectoryOperationEnabled())
78 return path.AsUTF8Unsafe();
79
80 return fileapi::FilePathToString(
81 base::FilePath(fileapi::VirtualPath::GetNormalizedFilePath(path)));
82 }
83
84 base::FilePath TitleToPath(const std::string& title) {
85 if (!IsSyncDirectoryOperationEnabled())
86 return base::FilePath::FromUTF8Unsafe(title);
87
88 return fileapi::StringToFilePath(title).NormalizePathSeparators();
89 }
90
91 DriveMetadata::ResourceType SyncFileTypeToDriveMetadataResourceType(
92 SyncFileType file_type) {
93 DCHECK_NE(SYNC_FILE_TYPE_UNKNOWN, file_type);
94 switch (file_type) {
95 case SYNC_FILE_TYPE_UNKNOWN:
96 return DriveMetadata_ResourceType_RESOURCE_TYPE_FILE;
97 case SYNC_FILE_TYPE_FILE:
98 return DriveMetadata_ResourceType_RESOURCE_TYPE_FILE;
99 case SYNC_FILE_TYPE_DIRECTORY:
100 return DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER;
101 }
102 NOTREACHED();
103 return DriveMetadata_ResourceType_RESOURCE_TYPE_FILE;
104 }
105
106 void SyncFileCallbackAdapter( 79 void SyncFileCallbackAdapter(
107 const SyncStatusCallback& status_callback, 80 const SyncStatusCallback& status_callback,
108 const SyncFileCallback& callback, 81 const SyncFileCallback& callback,
109 SyncStatusCode status, 82 SyncStatusCode status,
110 const FileSystemURL& url) { 83 const FileSystemURL& url) {
111 status_callback.Run(status); 84 status_callback.Run(status);
112 callback.Run(status, url); 85 callback.Run(status, url);
113 } 86 }
114 87
115 } // namespace 88 } // namespace
(...skipping 18 matching lines...) Expand all
134 const RemoteChangeHandler::RemoteChange& remote_change, 107 const RemoteChangeHandler::RemoteChange& remote_change,
135 const SyncFileCallback& callback) 108 const SyncFileCallback& callback)
136 : remote_change(remote_change), 109 : remote_change(remote_change),
137 callback(callback), 110 callback(callback),
138 metadata_updated(false), 111 metadata_updated(false),
139 sync_action(SYNC_ACTION_NONE), 112 sync_action(SYNC_ACTION_NONE),
140 clear_local_changes(true) { 113 clear_local_changes(true) {
141 } 114 }
142 }; 115 };
143 116
144 struct DriveFileSyncService::ApplyLocalChangeParam {
145 FileSystemURL url;
146 FileChange local_change;
147 base::FilePath local_path;
148 SyncFileMetadata local_metadata;
149 DriveMetadata drive_metadata;
150 bool has_drive_metadata;
151 SyncStatusCallback callback;
152
153 ApplyLocalChangeParam(const FileSystemURL& url,
154 const FileChange& local_change,
155 const base::FilePath& local_path,
156 const SyncFileMetadata& local_metadata,
157 const SyncStatusCallback& callback)
158 : url(url),
159 local_change(local_change),
160 local_path(local_path),
161 local_metadata(local_metadata),
162 has_drive_metadata(false),
163 callback(callback) {}
164 };
165
166 // DriveFileSyncService ------------------------------------------------------ 117 // DriveFileSyncService ------------------------------------------------------
167 118
168 DriveFileSyncService::~DriveFileSyncService() { 119 DriveFileSyncService::~DriveFileSyncService() {
169 if (api_util_) 120 if (api_util_)
170 api_util_->RemoveObserver(this); 121 api_util_->RemoveObserver(this);
171 122
172 google_apis::DriveNotificationManager* drive_notification_manager = 123 google_apis::DriveNotificationManager* drive_notification_manager =
173 google_apis::DriveNotificationManagerFactory::GetForProfile(profile_); 124 google_apis::DriveNotificationManagerFactory::GetForProfile(profile_);
174 if (drive_notification_manager) 125 if (drive_notification_manager)
175 drive_notification_manager->RemoveObserver(this); 126 drive_notification_manager->RemoveObserver(this);
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 base::Bind(&DriveFileSyncService::DidPrepareForProcessRemoteChange, 585 base::Bind(&DriveFileSyncService::DidPrepareForProcessRemoteChange,
635 AsWeakPtr(), base::Passed(&param))); 586 AsWeakPtr(), base::Passed(&param)));
636 } 587 }
637 588
638 void DriveFileSyncService::DoApplyLocalChange( 589 void DriveFileSyncService::DoApplyLocalChange(
639 const FileChange& local_file_change, 590 const FileChange& local_file_change,
640 const base::FilePath& local_file_path, 591 const base::FilePath& local_file_path,
641 const SyncFileMetadata& local_file_metadata, 592 const SyncFileMetadata& local_file_metadata,
642 const FileSystemURL& url, 593 const FileSystemURL& url,
643 const SyncStatusCallback& callback) { 594 const SyncStatusCallback& callback) {
644 // TODO(nhiroki): support directory operations (http://crbug.com/161442).
645 DCHECK(IsSyncDirectoryOperationEnabled() ||
646 !local_file_change.IsDirectory());
647
648 if (GetCurrentState() == REMOTE_SERVICE_DISABLED) { 595 if (GetCurrentState() == REMOTE_SERVICE_DISABLED) {
649 callback.Run(SYNC_STATUS_SYNC_DISABLED); 596 callback.Run(SYNC_STATUS_SYNC_DISABLED);
650 return; 597 return;
651 } 598 }
652 599
653 if (!metadata_store_->IsIncrementalSyncOrigin(url.origin()) && 600 if (!metadata_store_->IsIncrementalSyncOrigin(url.origin()) &&
654 !metadata_store_->IsBatchSyncOrigin(url.origin())) { 601 !metadata_store_->IsBatchSyncOrigin(url.origin())) {
655 // We may get called by LocalFileSyncService to sync local changes 602 // We may get called by LocalFileSyncService to sync local changes
656 // for the origins that are disabled. 603 // for the origins that are disabled.
657 DVLOG(1) << "Got request for stray origin: " << url.origin().spec(); 604 DVLOG(1) << "Got request for stray origin: " << url.origin().spec();
658 callback.Run(SYNC_STATUS_UNKNOWN_ORIGIN); 605 callback.Run(SYNC_STATUS_UNKNOWN_ORIGIN);
659 return; 606 return;
660 } 607 }
661 608
662 DriveMetadata metadata; 609 DCHECK(!running_local_sync_task_);
663 const bool has_metadata = 610 running_local_sync_task_.reset(new drive::LocalChangeProcessorDelegate(
664 (metadata_store_->ReadEntry(url, &metadata) == SYNC_STATUS_OK); 611 AsWeakPtr(), local_file_change, local_file_path,
665 612 local_file_metadata, url));
666 scoped_ptr<ApplyLocalChangeParam> param(new ApplyLocalChangeParam( 613 running_local_sync_task_->Run(base::Bind(
667 url, local_file_change, local_file_path, local_file_metadata, callback)); 614 &DriveFileSyncService::DidApplyLocalChange, AsWeakPtr(), callback));
668 param->has_drive_metadata = has_metadata;
669 param->drive_metadata = metadata;
670 if (!has_metadata)
671 param->drive_metadata.set_md5_checksum(std::string());
672
673 EnsureOriginRootDirectory(
674 url.origin(),
675 base::Bind(&DriveFileSyncService::ApplyLocalChangeInternal,
676 AsWeakPtr(), base::Passed(&param)));
677 } 615 }
678 616
679 void DriveFileSyncService::UpdateRegisteredOrigins() { 617 void DriveFileSyncService::UpdateRegisteredOrigins() {
680 ExtensionService* extension_service = 618 ExtensionService* extension_service =
681 extensions::ExtensionSystem::Get(profile_)->extension_service(); 619 extensions::ExtensionSystem::Get(profile_)->extension_service();
682 if (!extension_service) 620 if (!extension_service)
683 return; 621 return;
684 622
685 std::vector<GURL> origins; 623 std::vector<GURL> origins;
686 metadata_store_->GetAllOrigins(&origins); 624 metadata_store_->GetAllOrigins(&origins);
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 // Move |origin| to the incremental sync origin set if the origin has no file. 780 // Move |origin| to the incremental sync origin set if the origin has no file.
843 if (metadata_store_->IsBatchSyncOrigin(origin) && 781 if (metadata_store_->IsBatchSyncOrigin(origin) &&
844 !remote_change_handler_.HasChangesForOrigin(origin)) { 782 !remote_change_handler_.HasChangesForOrigin(origin)) {
845 metadata_store_->MoveBatchSyncOriginToIncremental(origin); 783 metadata_store_->MoveBatchSyncOriginToIncremental(origin);
846 } 784 }
847 785
848 may_have_unfetched_changes_ = true; 786 may_have_unfetched_changes_ = true;
849 callback.Run(SYNC_STATUS_OK); 787 callback.Run(SYNC_STATUS_OK);
850 } 788 }
851 789
852 void DriveFileSyncService::ApplyLocalChangeInternal( 790 ConflictResolutionResult DriveFileSyncService::ResolveConflictForLocalSync(
853 scoped_ptr<ApplyLocalChangeParam> param, 791 SyncFileType local_file_type,
854 SyncStatusCode status, 792 const base::Time& local_updated_time,
855 const std::string& origin_resource_id) { 793 SyncFileType remote_file_type,
856 if (status != SYNC_STATUS_OK) { 794 const base::Time& remote_updated_time) {
857 param->callback.Run(status); 795 // Currently we always prioritize directories over files regardless of
858 return; 796 // conflict resolution policy.
797 if (remote_file_type == SYNC_FILE_TYPE_DIRECTORY)
798 return CONFLICT_RESOLUTION_REMOTE_WIN;
799
800 if (conflict_resolution_ == CONFLICT_RESOLUTION_MANUAL)
801 return CONFLICT_RESOLUTION_MARK_CONFLICT;
802
803 DCHECK_EQ(CONFLICT_RESOLUTION_LAST_WRITE_WIN, conflict_resolution_);
804 if (local_updated_time >= remote_updated_time ||
805 remote_file_type == SYNC_FILE_TYPE_UNKNOWN) {
806 return CONFLICT_RESOLUTION_LOCAL_WIN;
859 } 807 }
860 808
861 const FileSystemURL& url = param->url; 809 return CONFLICT_RESOLUTION_REMOTE_WIN;
862 const FileChange& local_file_change = param->local_change;
863 const base::FilePath& local_file_path = param->local_path;
864 DriveMetadata& drive_metadata = param->drive_metadata;
865 const SyncStatusCallback& callback = param->callback;
866
867 RemoteChangeHandler::RemoteChange remote_change;
868 const bool has_remote_change =
869 remote_change_handler_.GetChangeForURL(url, &remote_change);
870 if (has_remote_change && param->drive_metadata.resource_id().empty())
871 param->drive_metadata.set_resource_id(remote_change.resource_id);
872
873 LocalSyncOperationType operation =
874 LocalSyncOperationResolver::Resolve(
875 local_file_change,
876 has_remote_change ? &remote_change.change : NULL,
877 param->has_drive_metadata ? &drive_metadata : NULL);
878
879 DVLOG(1) << "ApplyLocalChange for " << url.DebugString()
880 << " local_change:" << local_file_change.DebugString()
881 << " ==> operation:" << operation;
882
883 switch (operation) {
884 case LOCAL_SYNC_OPERATION_ADD_FILE:
885 api_util_->UploadNewFile(
886 origin_resource_id,
887 local_file_path,
888 PathToTitle(url.path()),
889 base::Bind(&DriveFileSyncService::DidUploadNewFileForLocalSync,
890 AsWeakPtr(),
891 base::Passed(&param)));
892 return;
893 case LOCAL_SYNC_OPERATION_ADD_DIRECTORY:
894 DCHECK(IsSyncDirectoryOperationEnabled());
895 api_util_->CreateDirectory(
896 origin_resource_id,
897 PathToTitle(url.path()),
898 base::Bind(&DriveFileSyncService::DidCreateDirectoryForLocalSync,
899 AsWeakPtr(),
900 base::Passed(&param)));
901 return;
902 case LOCAL_SYNC_OPERATION_UPDATE_FILE:
903 DCHECK(param->has_drive_metadata);
904 api_util_->UploadExistingFile(
905 drive_metadata.resource_id(),
906 drive_metadata.md5_checksum(),
907 local_file_path,
908 base::Bind(&DriveFileSyncService::DidUploadExistingFileForLocalSync,
909 AsWeakPtr(),
910 base::Passed(&param)));
911 return;
912 case LOCAL_SYNC_OPERATION_DELETE_FILE:
913 DCHECK(param->has_drive_metadata);
914 api_util_->DeleteFile(
915 drive_metadata.resource_id(),
916 drive_metadata.md5_checksum(),
917 base::Bind(&DriveFileSyncService::DidDeleteFileForLocalSync,
918 AsWeakPtr(),
919 base::Passed(&param)));
920 return;
921 case LOCAL_SYNC_OPERATION_DELETE_DIRECTORY:
922 DCHECK(IsSyncDirectoryOperationEnabled());
923 DCHECK(param->has_drive_metadata);
924 // This does not handle recursive directory deletion
925 // (which should not happen other than after a restart).
926 api_util_->DeleteFile(
927 drive_metadata.resource_id(),
928 std::string(), // empty etag
929 base::Bind(&DriveFileSyncService::DidDeleteFileForLocalSync,
930 AsWeakPtr(),
931 base::Passed(&param)));
932 return;
933 case LOCAL_SYNC_OPERATION_NONE:
934 callback.Run(SYNC_STATUS_OK);
935 return;
936 case LOCAL_SYNC_OPERATION_CONFLICT:
937 HandleConflictForLocalSync(param.Pass());
938 return;
939 case LOCAL_SYNC_OPERATION_RESOLVE_TO_LOCAL:
940 api_util_->DeleteFile(
941 drive_metadata.resource_id(),
942 drive_metadata.md5_checksum(),
943 base::Bind(
944 &DriveFileSyncService::DidDeleteForResolveToLocalForLocalSync,
945 AsWeakPtr(),
946 origin_resource_id,
947 local_file_path,
948 url,
949 base::Passed(&param)));
950 return;
951 case LOCAL_SYNC_OPERATION_RESOLVE_TO_REMOTE:
952 ResolveConflictToRemoteForLocalSync(
953 param.Pass(),
954 remote_change.change.file_type());
955 return;
956 case LOCAL_SYNC_OPERATION_DELETE_METADATA:
957 metadata_store_->DeleteEntry(
958 url,
959 base::Bind(&DriveFileSyncService::DidApplyLocalChange,
960 AsWeakPtr(), base::Passed(&param),
961 google_apis::HTTP_SUCCESS));
962 return;
963 case LOCAL_SYNC_OPERATION_FAIL: {
964 callback.Run(SYNC_STATUS_FAILED);
965 return;
966 }
967 }
968 NOTREACHED();
969 callback.Run(SYNC_STATUS_FAILED);
970 }
971
972 void DriveFileSyncService::DidDeleteForResolveToLocalForLocalSync(
973 const std::string& origin_resource_id,
974 const base::FilePath& local_file_path,
975 const fileapi::FileSystemURL& url,
976 scoped_ptr<ApplyLocalChangeParam> param,
977 google_apis::GDataErrorCode error) {
978 if (error != google_apis::HTTP_SUCCESS &&
979 error != google_apis::HTTP_NOT_FOUND) {
980 RemoveRemoteChange(param->url);
981 param->callback.Run(GDataErrorCodeToSyncStatusCodeWrapper(error));
982 return;
983 }
984
985 DCHECK_NE(SYNC_FILE_TYPE_UNKNOWN, param->local_metadata.file_type);
986 if (param->local_metadata.file_type == SYNC_FILE_TYPE_FILE) {
987 api_util_->UploadNewFile(
988 origin_resource_id,
989 local_file_path,
990 PathToTitle(url.path()),
991 base::Bind(&DriveFileSyncService::DidUploadNewFileForLocalSync,
992 AsWeakPtr(),
993 base::Passed(&param)));
994 return;
995 }
996
997 DCHECK(IsSyncDirectoryOperationEnabled());
998 DCHECK_EQ(SYNC_FILE_TYPE_DIRECTORY, param->local_metadata.file_type);
999 api_util_->CreateDirectory(
1000 origin_resource_id,
1001 PathToTitle(url.path()),
1002 base::Bind(&DriveFileSyncService::DidCreateDirectoryForLocalSync,
1003 AsWeakPtr(),
1004 base::Passed(&param)));
1005 } 810 }
1006 811
1007 void DriveFileSyncService::DidApplyLocalChange( 812 void DriveFileSyncService::DidApplyLocalChange(
1008 scoped_ptr<ApplyLocalChangeParam> param, 813 const SyncStatusCallback& callback,
1009 const google_apis::GDataErrorCode error,
1010 SyncStatusCode status) { 814 SyncStatusCode status) {
1011 if (status == SYNC_STATUS_OK) { 815 running_local_sync_task_.reset();
1012 RemoveRemoteChange(param->url); 816 callback.Run(status);
1013 status = GDataErrorCodeToSyncStatusCodeWrapper(error);
1014 }
1015 param->callback.Run(status);
1016 }
1017
1018 void DriveFileSyncService::DidResolveConflictToRemoteChange(
1019 scoped_ptr<ApplyLocalChangeParam> param,
1020 SyncStatusCode status) {
1021 DCHECK(param->has_drive_metadata);
1022 if (status != SYNC_STATUS_OK) {
1023 param->callback.Run(status);
1024 return;
1025 }
1026
1027 SyncFileType file_type = SYNC_FILE_TYPE_FILE;
1028 if (param->drive_metadata.type() == DriveMetadata::RESOURCE_TYPE_FOLDER)
1029 file_type = SYNC_FILE_TYPE_DIRECTORY;
1030 AppendFetchChange(param->url.origin(), param->url.path(),
1031 param->drive_metadata.resource_id(),
1032 file_type);
1033 param->callback.Run(status);
1034 }
1035
1036 void DriveFileSyncService::DidUploadNewFileForLocalSync(
1037 scoped_ptr<ApplyLocalChangeParam> param,
1038 google_apis::GDataErrorCode error,
1039 const std::string& resource_id,
1040 const std::string& file_md5) {
1041 DCHECK(param);
1042 const FileSystemURL& url = param->url;
1043 switch (error) {
1044 case google_apis::HTTP_CREATED: {
1045 param->drive_metadata.set_resource_id(resource_id);
1046 param->drive_metadata.set_md5_checksum(file_md5);
1047 param->drive_metadata.set_conflicted(false);
1048 param->drive_metadata.set_to_be_fetched(false);
1049 param->drive_metadata.set_type(DriveMetadata::RESOURCE_TYPE_FILE);
1050 const DriveMetadata& metadata = param->drive_metadata;
1051 metadata_store_->UpdateEntry(
1052 url, metadata,
1053 base::Bind(&DriveFileSyncService::DidApplyLocalChange,
1054 AsWeakPtr(), base::Passed(&param), error));
1055 NotifyObserversFileStatusChanged(url,
1056 SYNC_FILE_STATUS_SYNCED,
1057 SYNC_ACTION_ADDED,
1058 SYNC_DIRECTION_LOCAL_TO_REMOTE);
1059 return;
1060 }
1061 case google_apis::HTTP_CONFLICT:
1062 // File-file conflict is found.
1063 // Populates a fake drive_metadata and set has_drive_metadata = true.
1064 // In HandleConflictLocalSync:
1065 // - If conflict_resolution is manual, we'll change conflicted to true
1066 // and save the metadata.
1067 // - Otherwise we'll save the metadata with empty md5 and will start
1068 // over local sync as UploadExistingFile.
1069 param->drive_metadata.set_resource_id(resource_id);
1070 param->drive_metadata.set_md5_checksum(std::string());
1071 param->drive_metadata.set_conflicted(false);
1072 param->drive_metadata.set_to_be_fetched(false);
1073 param->drive_metadata.set_type(DriveMetadata::RESOURCE_TYPE_FILE);
1074 param->has_drive_metadata = true;
1075 HandleConflictForLocalSync(param.Pass());
1076 return;
1077
1078 default:
1079 param->callback.Run(GDataErrorCodeToSyncStatusCodeWrapper(error));
1080 }
1081 }
1082
1083 void DriveFileSyncService::DidCreateDirectoryForLocalSync(
1084 scoped_ptr<ApplyLocalChangeParam> param,
1085 google_apis::GDataErrorCode error,
1086 const std::string& resource_id) {
1087 DCHECK(param);
1088 const FileSystemURL& url = param->url;
1089 switch (error) {
1090 case google_apis::HTTP_SUCCESS:
1091 case google_apis::HTTP_CREATED: {
1092 param->drive_metadata.set_resource_id(resource_id);
1093 param->drive_metadata.set_md5_checksum(std::string());
1094 param->drive_metadata.set_conflicted(false);
1095 param->drive_metadata.set_to_be_fetched(false);
1096 param->drive_metadata.set_type(DriveMetadata::RESOURCE_TYPE_FOLDER);
1097 const DriveMetadata& metadata = param->drive_metadata;
1098 metadata_store_->UpdateEntry(
1099 url, metadata,
1100 base::Bind(&DriveFileSyncService::DidApplyLocalChange,
1101 AsWeakPtr(), base::Passed(&param), error));
1102 NotifyObserversFileStatusChanged(url,
1103 SYNC_FILE_STATUS_SYNCED,
1104 SYNC_ACTION_ADDED,
1105 SYNC_DIRECTION_LOCAL_TO_REMOTE);
1106 return;
1107 }
1108
1109 case google_apis::HTTP_CONFLICT:
1110 // There were conflicts and a file was left.
1111 // TODO(kinuko): Handle the latter case (http://crbug.com/237090).
1112 // Fall-through
1113
1114 default:
1115 param->callback.Run(GDataErrorCodeToSyncStatusCodeWrapper(error));
1116 }
1117 }
1118
1119 void DriveFileSyncService::DidUploadExistingFileForLocalSync(
1120 scoped_ptr<ApplyLocalChangeParam> param,
1121 google_apis::GDataErrorCode error,
1122 const std::string& resource_id,
1123 const std::string& file_md5) {
1124 DCHECK(param);
1125 DCHECK(param->has_drive_metadata);
1126 const FileSystemURL& url = param->url;
1127 switch (error) {
1128 case google_apis::HTTP_SUCCESS: {
1129 param->drive_metadata.set_resource_id(resource_id);
1130 param->drive_metadata.set_md5_checksum(file_md5);
1131 param->drive_metadata.set_conflicted(false);
1132 param->drive_metadata.set_to_be_fetched(false);
1133 param->drive_metadata.set_type(DriveMetadata::RESOURCE_TYPE_FILE);
1134 const DriveMetadata& metadata = param->drive_metadata;
1135 metadata_store_->UpdateEntry(
1136 url, metadata,
1137 base::Bind(&DriveFileSyncService::DidApplyLocalChange,
1138 AsWeakPtr(), base::Passed(&param), error));
1139 NotifyObserversFileStatusChanged(url,
1140 SYNC_FILE_STATUS_SYNCED,
1141 SYNC_ACTION_UPDATED,
1142 SYNC_DIRECTION_LOCAL_TO_REMOTE);
1143 return;
1144 }
1145 case google_apis::HTTP_CONFLICT: {
1146 HandleConflictForLocalSync(param.Pass());
1147 return;
1148 }
1149 case google_apis::HTTP_NOT_MODIFIED: {
1150 DidApplyLocalChange(param.Pass(),
1151 google_apis::HTTP_SUCCESS, SYNC_STATUS_OK);
1152 return;
1153 }
1154 case google_apis::HTTP_NOT_FOUND: {
1155 const base::FilePath& local_file_path = param->local_path;
1156 api_util_->UploadNewFile(
1157 metadata_store_->GetResourceIdForOrigin(url.origin()),
1158 local_file_path,
1159 PathToTitle(url.path()),
1160 base::Bind(&DriveFileSyncService::DidUploadNewFileForLocalSync,
1161 AsWeakPtr(),
1162 base::Passed(&param)));
1163 return;
1164 }
1165 default: {
1166 const SyncStatusCode status =
1167 GDataErrorCodeToSyncStatusCodeWrapper(error);
1168 DCHECK_NE(SYNC_STATUS_OK, status);
1169 param->callback.Run(status);
1170 return;
1171 }
1172 }
1173 }
1174
1175 void DriveFileSyncService::DidDeleteFileForLocalSync(
1176 scoped_ptr<ApplyLocalChangeParam> param,
1177 google_apis::GDataErrorCode error) {
1178 DCHECK(param);
1179 DCHECK(param->has_drive_metadata);
1180 const FileSystemURL& url = param->url;
1181 switch (error) {
1182 // Regardless of whether the deletion has succeeded (HTTP_SUCCESS) or
1183 // has failed with ETag conflict error (HTTP_PRECONDITION or HTTP_CONFLICT)
1184 // we should just delete the drive_metadata.
1185 // In the former case the file should be just gone now, and
1186 // in the latter case the remote change will be applied in a future
1187 // remote sync.
1188 case google_apis::HTTP_SUCCESS:
1189 case google_apis::HTTP_PRECONDITION:
1190 case google_apis::HTTP_CONFLICT:
1191 metadata_store_->DeleteEntry(
1192 url,
1193 base::Bind(&DriveFileSyncService::DidApplyLocalChange,
1194 AsWeakPtr(), base::Passed(&param), error));
1195 NotifyObserversFileStatusChanged(url,
1196 SYNC_FILE_STATUS_SYNCED,
1197 SYNC_ACTION_DELETED,
1198 SYNC_DIRECTION_LOCAL_TO_REMOTE);
1199 return;
1200 case google_apis::HTTP_NOT_FOUND:
1201 DidApplyLocalChange(param.Pass(),
1202 google_apis::HTTP_SUCCESS, SYNC_STATUS_OK);
1203 return;
1204 default: {
1205 const SyncStatusCode status =
1206 GDataErrorCodeToSyncStatusCodeWrapper(error);
1207 DCHECK_NE(SYNC_STATUS_OK, status);
1208 param->callback.Run(status);
1209 return;
1210 }
1211 }
1212 }
1213
1214 void DriveFileSyncService::HandleConflictForLocalSync(
1215 scoped_ptr<ApplyLocalChangeParam> param) {
1216 DCHECK(param);
1217 DriveMetadata& drive_metadata = param->drive_metadata;
1218 DCHECK(!drive_metadata.resource_id().empty());
1219
1220 api_util_->GetResourceEntry(
1221 drive_metadata.resource_id(),
1222 base::Bind(
1223 &DriveFileSyncService::DidGetRemoteFileMetadataForRemoteUpdatedTime,
1224 AsWeakPtr(),
1225 base::Bind(&DriveFileSyncService::ResolveConflictForLocalSync,
1226 AsWeakPtr(),
1227 base::Passed(&param))));
1228 }
1229
1230 void DriveFileSyncService::ResolveConflictForLocalSync(
1231 scoped_ptr<ApplyLocalChangeParam> param,
1232 const base::Time& remote_updated_time,
1233 SyncFileType remote_file_type,
1234 SyncStatusCode status) {
1235 DCHECK(param);
1236 const FileSystemURL& url = param->url;
1237 DriveMetadata& drive_metadata = param->drive_metadata;
1238 SyncFileMetadata& local_metadata = param->local_metadata;
1239 if (status != SYNC_STATUS_OK) {
1240 param->callback.Run(status);
1241 return;
1242 }
1243
1244 // Currently we always prioritize directories over files regardless of
1245 // conflict resolution policy.
1246 DCHECK(param->local_change.IsFile());
1247 if (remote_file_type == SYNC_FILE_TYPE_DIRECTORY) {
1248 ResolveConflictToRemoteForLocalSync(param.Pass(), SYNC_FILE_TYPE_DIRECTORY);
1249 return;
1250 }
1251
1252 if (conflict_resolution_ == CONFLICT_RESOLUTION_MANUAL) {
1253 if (drive_metadata.conflicted()) {
1254 // It's already conflicting; no need to update metadata.
1255 param->callback.Run(SYNC_STATUS_FAILED);
1256 return;
1257 }
1258 MarkConflict(url, &drive_metadata,
1259 base::Bind(&DriveFileSyncService::DidApplyLocalChange,
1260 AsWeakPtr(), base::Passed(&param),
1261 google_apis::HTTP_CONFLICT));
1262 return;
1263 }
1264
1265 DCHECK_EQ(CONFLICT_RESOLUTION_LAST_WRITE_WIN, conflict_resolution_);
1266
1267 if (local_metadata.last_modified >= remote_updated_time ||
1268 remote_file_type == SYNC_FILE_TYPE_UNKNOWN) {
1269 // Local win case.
1270 DVLOG(1) << "Resolving conflict for local sync:"
1271 << url.DebugString() << ": LOCAL WIN";
1272 if (!param->has_drive_metadata) {
1273 StartOverLocalSync(param.Pass(), SYNC_STATUS_OK);
1274 return;
1275 }
1276 // Make sure we reset the conflict flag and start over the local sync
1277 // with empty remote changes.
1278 DCHECK(!drive_metadata.resource_id().empty());
1279 drive_metadata.set_md5_checksum(std::string());
1280 drive_metadata.set_conflicted(false);
1281 drive_metadata.set_to_be_fetched(false);
1282 drive_metadata.set_type(
1283 SyncFileTypeToDriveMetadataResourceType(SYNC_FILE_TYPE_FILE));
1284 metadata_store_->UpdateEntry(
1285 url, drive_metadata,
1286 base::Bind(&DriveFileSyncService::StartOverLocalSync, AsWeakPtr(),
1287 base::Passed(&param)));
1288 return;
1289 }
1290 // Remote win case.
1291 DVLOG(1) << "Resolving conflict for local sync:"
1292 << url.DebugString() << ": REMOTE WIN";
1293 ResolveConflictToRemoteForLocalSync(param.Pass(), SYNC_FILE_TYPE_FILE);
1294 }
1295
1296 void DriveFileSyncService::ResolveConflictToRemoteForLocalSync(
1297 scoped_ptr<ApplyLocalChangeParam> param,
1298 SyncFileType remote_file_type) {
1299 DCHECK(param);
1300 const FileSystemURL& url = param->url;
1301 DriveMetadata& drive_metadata = param->drive_metadata;
1302 // Mark the file as to-be-fetched.
1303 DCHECK(!drive_metadata.resource_id().empty());
1304 drive_metadata.set_conflicted(false);
1305 drive_metadata.set_to_be_fetched(true);
1306 drive_metadata.set_type(
1307 SyncFileTypeToDriveMetadataResourceType(remote_file_type));
1308 param->has_drive_metadata = true;
1309 metadata_store_->UpdateEntry(
1310 url, drive_metadata,
1311 base::Bind(&DriveFileSyncService::DidResolveConflictToRemoteChange,
1312 AsWeakPtr(), base::Passed(&param)));
1313 // The synced notification will be dispatched when the remote file is
1314 // downloaded.
1315 }
1316
1317 void DriveFileSyncService::StartOverLocalSync(
1318 scoped_ptr<ApplyLocalChangeParam> param,
1319 SyncStatusCode status) {
1320 DCHECK(param);
1321 if (status != SYNC_STATUS_OK) {
1322 param->callback.Run(status);
1323 return;
1324 }
1325 RemoveRemoteChange(param->url);
1326 DoApplyLocalChange(
1327 param->local_change, param->local_path, param->local_metadata,
1328 param->url, param->callback);
1329 } 817 }
1330 818
1331 void DriveFileSyncService::DidPrepareForProcessRemoteChange( 819 void DriveFileSyncService::DidPrepareForProcessRemoteChange(
1332 scoped_ptr<ProcessRemoteChangeParam> param, 820 scoped_ptr<ProcessRemoteChangeParam> param,
1333 SyncStatusCode status, 821 SyncStatusCode status,
1334 const SyncFileMetadata& metadata, 822 const SyncFileMetadata& metadata,
1335 const FileChangeList& local_changes) { 823 const FileChangeList& local_changes) {
1336 if (status != SYNC_STATUS_OK) { 824 if (status != SYNC_STATUS_OK) {
1337 AbortRemoteSync(param.Pass(), status); 825 AbortRemoteSync(param.Pass(), status);
1338 return; 826 return;
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after
1978 1466
1979 MaybeStartFetchChanges(); 1467 MaybeStartFetchChanges();
1980 } 1468 }
1981 1469
1982 void DriveFileSyncService::NotifyLastOperationStatus( 1470 void DriveFileSyncService::NotifyLastOperationStatus(
1983 SyncStatusCode sync_status, 1471 SyncStatusCode sync_status,
1984 google_apis::GDataErrorCode gdata_error) { 1472 google_apis::GDataErrorCode gdata_error) {
1985 UpdateServiceStateFromLastOperationStatus(sync_status, gdata_error); 1473 UpdateServiceStateFromLastOperationStatus(sync_status, gdata_error);
1986 } 1474 }
1987 1475
1476 // static
1477 std::string DriveFileSyncService::PathToTitle(const base::FilePath& path) {
1478 if (!IsSyncDirectoryOperationEnabled())
1479 return path.AsUTF8Unsafe();
1480
1481 return fileapi::FilePathToString(
1482 base::FilePath(fileapi::VirtualPath::GetNormalizedFilePath(path)));
1483 }
1484
1485 // static
1486 base::FilePath DriveFileSyncService::TitleToPath(const std::string& title) {
1487 if (!IsSyncDirectoryOperationEnabled())
1488 return base::FilePath::FromUTF8Unsafe(title);
1489
1490 return fileapi::StringToFilePath(title).NormalizePathSeparators();
1491 }
1492
1493 // static
1494 DriveMetadata::ResourceType
1495 DriveFileSyncService::SyncFileTypeToDriveMetadataResourceType(
kinuko 2013/05/16 13:37:37 nit: maybe we can factor out these util methods in
tzik 2013/05/17 05:14:10 Done.
1496 SyncFileType file_type) {
1497 DCHECK_NE(SYNC_FILE_TYPE_UNKNOWN, file_type);
1498 switch (file_type) {
1499 case SYNC_FILE_TYPE_UNKNOWN:
1500 return DriveMetadata_ResourceType_RESOURCE_TYPE_FILE;
1501 case SYNC_FILE_TYPE_FILE:
1502 return DriveMetadata_ResourceType_RESOURCE_TYPE_FILE;
1503 case SYNC_FILE_TYPE_DIRECTORY:
1504 return DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER;
1505 }
1506 NOTREACHED();
1507 return DriveMetadata_ResourceType_RESOURCE_TYPE_FILE;
1508 }
1509
1988 void DriveFileSyncService::FetchChangesForIncrementalSync( 1510 void DriveFileSyncService::FetchChangesForIncrementalSync(
1989 const SyncStatusCallback& callback) { 1511 const SyncStatusCallback& callback) {
1990 DCHECK(may_have_unfetched_changes_); 1512 DCHECK(may_have_unfetched_changes_);
1991 DCHECK(pending_batch_sync_origins_.empty()); 1513 DCHECK(pending_batch_sync_origins_.empty());
1992 DCHECK(!metadata_store_->incremental_sync_origins().empty()); 1514 DCHECK(!metadata_store_->incremental_sync_origins().empty());
1993 1515
1994 DVLOG(1) << "FetchChangesForIncrementalSync (start_changestamp:" 1516 DVLOG(1) << "FetchChangesForIncrementalSync (start_changestamp:"
1995 << (largest_fetched_changestamp_ + 1) << ")"; 1517 << (largest_fetched_changestamp_ + 1) << ")";
1996 1518
1997 api_util_->ListChanges( 1519 api_util_->ListChanges(
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
2182 pending_batch_sync_origins_.insert(origin); 1704 pending_batch_sync_origins_.insert(origin);
2183 } 1705 }
2184 callback.Run(status, resource_id); 1706 callback.Run(status, resource_id);
2185 } 1707 }
2186 1708
2187 std::string DriveFileSyncService::sync_root_resource_id() { 1709 std::string DriveFileSyncService::sync_root_resource_id() {
2188 return metadata_store_->sync_root_directory(); 1710 return metadata_store_->sync_root_directory();
2189 } 1711 }
2190 1712
2191 } // namespace sync_file_system 1713 } // namespace sync_file_system
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698