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

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

Powered by Google App Engine
This is Rietveld 408576698