1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h"
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/callback.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/format_macros.h"
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/location.h"
10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/logging.h"
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/strings/stringprintf.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/drive/drive_api_util.h"
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/drive/drive_service_interface.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/drive/drive_uploader.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/sync_file_system/logger.h"
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/drive/drive_api_parser.h"
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace sync_file_system {
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace drive_backend {
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ConflictResolver::ConflictResolver(SyncEngineContext* sync_context)
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : sync_context_(sync_context),
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      weak_ptr_factory_(this) {}
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
31effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochConflictResolver::~ConflictResolver() {}
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::RunPreflight(scoped_ptr<SyncTaskToken> token) {
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  token->InitializeTaskLog("Conflict Resolution");
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<TaskBlocker> task_blocker(new TaskBlocker);
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  task_blocker->exclusive = true;
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SyncTaskManager::UpdateTaskBlocker(
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      token.Pass(), task_blocker.Pass(),
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&ConflictResolver::RunExclusive,
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::RunExclusive(scoped_ptr<SyncTaskToken> token) {
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!IsContextReady()) {
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Conflict resolution should be invoked on clean tree.
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (metadata_database()->HasDirtyTracker()) {
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    NOTREACHED();
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TrackerIDSet trackers;
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (metadata_database()->GetMultiParentFileTrackers(
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          &target_file_id_, &trackers)) {
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK_LT(1u, trackers.size());
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!trackers.has_active()) {
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      NOTREACHED();
6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return;
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    token->RecordLog(base::StringPrintf(
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        "Detected multi-parent trackers (active tracker_id=%" PRId64 ")",
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        trackers.active_tracker()));
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(trackers.has_active());
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    for (TrackerIDSet::const_iterator itr = trackers.begin();
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         itr != trackers.end(); ++itr) {
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FileTracker tracker;
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (!metadata_database()->FindTrackerByTrackerID(*itr, &tracker)) {
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        NOTREACHED();
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        continue;
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (tracker.active())
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        continue;
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      FileTracker parent_tracker;
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      bool should_success = metadata_database()->FindTrackerByTrackerID(
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          tracker.parent_tracker_id(), &parent_tracker);
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (!should_success) {
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        NOTREACHED();
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return;
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      parents_to_remove_.push_back(parent_tracker.file_id());
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DetachFromNonPrimaryParents(token.Pass());
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (metadata_database()->GetConflictingTrackers(&trackers)) {
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    target_file_id_ = PickPrimaryFile(trackers);
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(!target_file_id_.empty());
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 primary_tracker_id = -1;
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    for (TrackerIDSet::const_iterator itr = trackers.begin();
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         itr != trackers.end(); ++itr) {
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FileTracker tracker;
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (!metadata_database()->FindTrackerByTrackerID(*itr, &tracker)) {
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        NOTREACHED();
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        continue;
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (tracker.file_id() != target_file_id_) {
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        non_primary_file_ids_.push_back(
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            std::make_pair(tracker.file_id(), tracker.synced_details().etag()));
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        primary_tracker_id = tracker.tracker_id();
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    token->RecordLog(base::StringPrintf(
11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        "Detected %" PRIuS " conflicting trackers "
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        "(primary tracker_id=%" PRId64 ")",
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        non_primary_file_ids_.size(), primary_tracker_id));
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    RemoveNonPrimaryFiles(token.Pass());
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_NO_CONFLICT);
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ConflictResolver::DetachFromNonPrimaryParents(
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<SyncTaskToken> token) {
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(!parents_to_remove_.empty());
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // TODO(tzik): Check if ETag match is available for
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // RemoteResourceFromDirectory.
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string parent_folder_id = parents_to_remove_.back();
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  parents_to_remove_.pop_back();
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  token->RecordLog(base::StringPrintf(
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      "Detach %s from %s",
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      target_file_id_.c_str(), parent_folder_id.c_str()));
14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  drive_service()->RemoveResourceFromDirectory(
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      parent_folder_id, target_file_id_,
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&ConflictResolver::DidDetachFromParent,
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Passed(&token)));
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::DidDetachFromParent(scoped_ptr<SyncTaskToken> token,
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                           google_apis::GDataErrorCode error) {
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (status != SYNC_STATUS_OK) {
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!parents_to_remove_.empty()) {
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DetachFromNonPrimaryParents(token.Pass());
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK);
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string ConflictResolver::PickPrimaryFile(const TrackerIDSet& trackers) {
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<FileMetadata> primary;
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (TrackerIDSet::const_iterator itr = trackers.begin();
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       itr != trackers.end(); ++itr) {
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FileTracker tracker;
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!metadata_database()->FindTrackerByTrackerID(*itr, &tracker)) {
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NOTREACHED();
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      continue;
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<FileMetadata> file_metadata(new FileMetadata);
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!metadata_database()->FindFileByFileID(
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            tracker.file_id(), file_metadata.get())) {
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      NOTREACHED();
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      continue;
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!primary) {
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      primary = file_metadata.Pass();
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      continue;
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(primary->details().file_kind() == FILE_KIND_FILE ||
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           primary->details().file_kind() == FILE_KIND_FOLDER);
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(file_metadata->details().file_kind() == FILE_KIND_FILE ||
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           file_metadata->details().file_kind() == FILE_KIND_FOLDER);
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (primary->details().file_kind() == FILE_KIND_FILE) {
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (file_metadata->details().file_kind() == FILE_KIND_FOLDER) {
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // Prioritize folders over regular files.
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        primary = file_metadata.Pass();
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        continue;
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DCHECK(file_metadata->details().file_kind() == FILE_KIND_FILE);
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (primary->details().modification_time() <
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          file_metadata->details().modification_time()) {
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // Prioritize last write for regular files.
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        primary = file_metadata.Pass();
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        continue;
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      continue;
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(primary->details().file_kind() == FILE_KIND_FOLDER);
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (file_metadata->details().file_kind() == FILE_KIND_FILE) {
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Prioritize folders over regular files.
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      continue;
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(file_metadata->details().file_kind() == FILE_KIND_FOLDER);
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (primary->details().creation_time() >
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        file_metadata->details().creation_time()) {
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Prioritize first create for folders.
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      primary = file_metadata.Pass();
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      continue;
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (primary)
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return primary->file_id();
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return std::string();
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::RemoveNonPrimaryFiles(scoped_ptr<SyncTaskToken> token) {
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(!non_primary_file_ids_.empty());
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string file_id = non_primary_file_ids_.back().first;
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string etag = non_primary_file_ids_.back().second;
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  non_primary_file_ids_.pop_back();
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK_NE(target_file_id_, file_id);
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  token->RecordLog(base::StringPrintf(
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      "Remove non-primary file %s", file_id.c_str()));
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // TODO(tzik): Check if the file is a folder, and merge its contents into
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // the folder identified by |target_file_id_|.
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  drive_service()->DeleteResource(
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      file_id, etag,
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&ConflictResolver::DidRemoveFile,
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Passed(&token), file_id));
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::DidRemoveFile(scoped_ptr<SyncTaskToken> token,
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                     const std::string& file_id,
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                     google_apis::GDataErrorCode error) {
253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (error == google_apis::HTTP_PRECONDITION ||
254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      error == google_apis::HTTP_CONFLICT) {
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    UpdateFileMetadata(file_id, token.Pass());
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (status != SYNC_STATUS_OK && error != google_apis::HTTP_NOT_FOUND) {
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  deleted_file_ids_.push_back(file_id);
266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!non_primary_file_ids_.empty()) {
26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    RemoveNonPrimaryFiles(token.Pass());
268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  status = metadata_database()->UpdateByDeletedRemoteFileList(
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      deleted_file_ids_);
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SyncTaskManager::NotifyTaskDone(token.Pass(), status);
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ConflictResolver::IsContextReady() {
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return sync_context_->GetDriveService() &&
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      sync_context_->GetMetadataDatabase();
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ConflictResolver::UpdateFileMetadata(
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& file_id,
28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<SyncTaskToken> token) {
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  drive_service()->GetFileResource(
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      file_id,
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&ConflictResolver::DidGetRemoteMetadata,
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(), file_id,
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Passed(&token)));
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ConflictResolver::DidGetRemoteMetadata(
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& file_id,
29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<SyncTaskToken> token,
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    google_apis::GDataErrorCode error,
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<google_apis::FileResource> entry) {
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (status != SYNC_STATUS_OK && error != google_apis::HTTP_NOT_FOUND) {
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != google_apis::HTTP_NOT_FOUND) {
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    status = metadata_database()->UpdateByDeletedRemoteFile(file_id);
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!entry) {
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NOTREACHED();
31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  status = metadata_database()->UpdateByFileResource(*entry);
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SyncTaskManager::NotifyTaskDone(token.Pass(), status);
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)drive::DriveServiceInterface* ConflictResolver::drive_service() {
319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  set_used_network(true);
320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return sync_context_->GetDriveService();
321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MetadataDatabase* ConflictResolver::metadata_database() {
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return sync_context_->GetMetadataDatabase();
325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace drive_backend
328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace sync_file_system
329