Home | History | Annotate | Download | only in drive_backend
      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