1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/sync_file_system/drive_backend/remote_sync_operation_resolver.h" 6 7 #include "base/logging.h" 8 9 namespace sync_file_system { 10 11 namespace { 12 13 bool IsValidCombination(const FileChangeList& local_changes, 14 SyncFileType local_file_type, 15 bool is_conflicting) { 16 if (local_changes.empty()) { 17 // We never leave directory or non-existing entry in conflicting state, so 18 // if there're no local changes it shouldn't be in conflicting state or 19 // should be a file. 20 return !(is_conflicting && local_file_type != SYNC_FILE_TYPE_FILE); 21 } 22 23 switch (local_file_type) { 24 case SYNC_FILE_TYPE_UNKNOWN: 25 return local_changes.back().IsDelete(); 26 case SYNC_FILE_TYPE_FILE: 27 case SYNC_FILE_TYPE_DIRECTORY: 28 return !local_changes.back().IsDelete() && 29 local_changes.back().file_type() == local_file_type; 30 } 31 return false; 32 } 33 34 } // namespace 35 36 SyncOperationType 37 RemoteSyncOperationResolver::Resolve(const FileChange& remote_file_change, 38 const FileChangeList& local_changes, 39 SyncFileType local_file_type, 40 bool is_conflicting) { 41 switch (remote_file_change.change()) { 42 case FileChange::FILE_CHANGE_ADD_OR_UPDATE: 43 switch (remote_file_change.file_type()) { 44 case SYNC_FILE_TYPE_FILE: 45 return is_conflicting 46 ? ResolveForAddOrUpdateFileInConflict(local_changes, 47 local_file_type) 48 : ResolveForAddOrUpdateFile(local_changes, local_file_type); 49 case SYNC_FILE_TYPE_DIRECTORY: 50 return is_conflicting 51 ? ResolveForAddDirectoryInConflict(local_changes, local_file_type) 52 : ResolveForAddDirectory(local_changes, local_file_type); 53 case SYNC_FILE_TYPE_UNKNOWN: 54 NOTREACHED(); 55 return SYNC_OPERATION_FAIL; 56 } 57 break; 58 case FileChange::FILE_CHANGE_DELETE: 59 switch (remote_file_change.file_type()) { 60 case SYNC_FILE_TYPE_FILE: 61 return is_conflicting 62 ? ResolveForDeleteFileInConflict(local_changes, local_file_type) 63 : ResolveForDeleteFile(local_changes, local_file_type); 64 case SYNC_FILE_TYPE_DIRECTORY: 65 return is_conflicting 66 ? ResolveForDeleteDirectoryInConflict(local_changes, 67 local_file_type) 68 : ResolveForDeleteDirectory(local_changes, local_file_type); 69 case SYNC_FILE_TYPE_UNKNOWN: 70 NOTREACHED(); 71 return SYNC_OPERATION_FAIL; 72 } 73 break; 74 } 75 NOTREACHED(); 76 return SYNC_OPERATION_FAIL; 77 } 78 79 SyncOperationType RemoteSyncOperationResolver::ResolveForAddOrUpdateFile( 80 const FileChangeList& local_changes, 81 SyncFileType local_file_type) { 82 // Invalid combination should never happen. 83 if (!IsValidCombination(local_changes, local_file_type, false)) 84 return SYNC_OPERATION_FAIL; 85 86 switch (local_file_type) { 87 case SYNC_FILE_TYPE_UNKNOWN: 88 return SYNC_OPERATION_ADD_FILE; 89 case SYNC_FILE_TYPE_FILE: 90 if (local_changes.empty()) 91 return SYNC_OPERATION_UPDATE_FILE; 92 return SYNC_OPERATION_CONFLICT; 93 case SYNC_FILE_TYPE_DIRECTORY: 94 // Currently we always prioritize directories over files. 95 return SYNC_OPERATION_RESOLVE_TO_LOCAL; 96 } 97 return SYNC_OPERATION_FAIL; 98 } 99 100 SyncOperationType 101 RemoteSyncOperationResolver::ResolveForAddOrUpdateFileInConflict( 102 const FileChangeList& local_changes, 103 SyncFileType local_file_type) { 104 // Invalid combination should never happen. 105 if (!IsValidCombination(local_changes, local_file_type, true)) 106 return SYNC_OPERATION_FAIL; 107 108 switch (local_file_type) { 109 case SYNC_FILE_TYPE_UNKNOWN: 110 return SYNC_OPERATION_RESOLVE_TO_REMOTE; 111 case SYNC_FILE_TYPE_FILE: 112 return SYNC_OPERATION_CONFLICT; 113 case SYNC_FILE_TYPE_DIRECTORY: 114 return SYNC_OPERATION_RESOLVE_TO_LOCAL; 115 } 116 return SYNC_OPERATION_FAIL; 117 } 118 119 SyncOperationType RemoteSyncOperationResolver::ResolveForAddDirectory( 120 const FileChangeList& local_changes, 121 SyncFileType local_file_type) { 122 // Invalid combination should never happen. 123 if (!IsValidCombination(local_changes, local_file_type, false)) 124 return SYNC_OPERATION_FAIL; 125 126 switch (local_file_type) { 127 case SYNC_FILE_TYPE_UNKNOWN: 128 if (local_changes.empty()) 129 return SYNC_OPERATION_ADD_DIRECTORY; 130 return SYNC_OPERATION_RESOLVE_TO_REMOTE; 131 case SYNC_FILE_TYPE_FILE: 132 return SYNC_OPERATION_RESOLVE_TO_REMOTE; 133 case SYNC_FILE_TYPE_DIRECTORY: 134 return SYNC_OPERATION_NONE; 135 } 136 return SYNC_OPERATION_FAIL; 137 } 138 139 SyncOperationType 140 RemoteSyncOperationResolver::ResolveForAddDirectoryInConflict( 141 const FileChangeList& local_changes, 142 SyncFileType local_file_type) { 143 // Invalid combination should never happen. 144 if (!IsValidCombination(local_changes, local_file_type, true)) 145 return SYNC_OPERATION_FAIL; 146 147 switch (local_file_type) { 148 case SYNC_FILE_TYPE_UNKNOWN: 149 case SYNC_FILE_TYPE_FILE: 150 return SYNC_OPERATION_RESOLVE_TO_REMOTE; 151 case SYNC_FILE_TYPE_DIRECTORY: 152 return SYNC_OPERATION_RESOLVE_TO_LOCAL; 153 } 154 return SYNC_OPERATION_FAIL; 155 } 156 157 SyncOperationType RemoteSyncOperationResolver::ResolveForDeleteFile( 158 const FileChangeList& local_changes, 159 SyncFileType local_file_type) { 160 // Invalid combination should never happen. 161 if (!IsValidCombination(local_changes, local_file_type, false)) 162 return SYNC_OPERATION_FAIL; 163 164 switch (local_file_type) { 165 case SYNC_FILE_TYPE_UNKNOWN: 166 return SYNC_OPERATION_DELETE_METADATA; 167 case SYNC_FILE_TYPE_FILE: 168 if (local_changes.empty()) 169 return SYNC_OPERATION_DELETE; 170 return SYNC_OPERATION_NONE; 171 case SYNC_FILE_TYPE_DIRECTORY: 172 return SYNC_OPERATION_NONE; 173 } 174 return SYNC_OPERATION_FAIL; 175 } 176 177 SyncOperationType 178 RemoteSyncOperationResolver::ResolveForDeleteFileInConflict( 179 const FileChangeList& local_changes, 180 SyncFileType local_file_type) { 181 // Invalid combination should never happen. 182 if (!IsValidCombination(local_changes, local_file_type, true)) 183 return SYNC_OPERATION_FAIL; 184 185 switch (local_file_type) { 186 case SYNC_FILE_TYPE_UNKNOWN: 187 return SYNC_OPERATION_DELETE_METADATA; 188 case SYNC_FILE_TYPE_FILE: 189 case SYNC_FILE_TYPE_DIRECTORY: 190 return SYNC_OPERATION_RESOLVE_TO_LOCAL; 191 } 192 return SYNC_OPERATION_FAIL; 193 } 194 195 SyncOperationType RemoteSyncOperationResolver::ResolveForDeleteDirectory( 196 const FileChangeList& local_changes, 197 SyncFileType local_file_type) { 198 // Invalid combination should never happen. 199 if (!IsValidCombination(local_changes, local_file_type, false)) 200 return SYNC_OPERATION_FAIL; 201 202 switch (local_file_type) { 203 case SYNC_FILE_TYPE_UNKNOWN: 204 return SYNC_OPERATION_NONE; 205 case SYNC_FILE_TYPE_FILE: 206 return SYNC_OPERATION_RESOLVE_TO_LOCAL; 207 case SYNC_FILE_TYPE_DIRECTORY: 208 if (local_changes.empty()) 209 return SYNC_OPERATION_DELETE; 210 return SYNC_OPERATION_RESOLVE_TO_LOCAL; 211 } 212 return SYNC_OPERATION_FAIL; 213 } 214 215 SyncOperationType 216 RemoteSyncOperationResolver::ResolveForDeleteDirectoryInConflict( 217 const FileChangeList& local_changes, 218 SyncFileType local_file_type) { 219 // Invalid combination should never happen. 220 if (!IsValidCombination(local_changes, local_file_type, true)) 221 return SYNC_OPERATION_FAIL; 222 223 switch (local_file_type) { 224 case SYNC_FILE_TYPE_UNKNOWN: 225 return SYNC_OPERATION_DELETE_METADATA; 226 case SYNC_FILE_TYPE_FILE: 227 case SYNC_FILE_TYPE_DIRECTORY: 228 return SYNC_OPERATION_RESOLVE_TO_LOCAL; 229 } 230 return SYNC_OPERATION_FAIL; 231 } 232 233 } // namespace sync_file_system 234