register_app_task.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/register_app_task.h" 6 7#include "base/bind.h" 8#include "base/location.h" 9#include "chrome/browser/drive/drive_api_util.h" 10#include "chrome/browser/drive/drive_service_interface.h" 11#include "chrome/browser/google_apis/drive_api_parser.h" 12#include "chrome/browser/google_apis/gdata_wapi_parser.h" 13#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h" 14#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 15#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" 16#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 17#include "chrome/browser/sync_file_system/drive_backend/tracker_set.h" 18#include "chrome/browser/sync_file_system/syncable_file_system_util.h" 19 20namespace sync_file_system { 21namespace drive_backend { 22 23namespace { 24 25bool CompareOnCTime(const FileTracker& left, 26 const FileTracker& right) { 27 return left.synced_details().creation_time() < 28 right.synced_details().creation_time(); 29} 30 31} // namespace 32 33RegisterAppTask::RegisterAppTask(SyncEngineContext* sync_context, 34 const std::string& app_id) 35 : sync_context_(sync_context), 36 create_folder_retry_count_(0), 37 app_id_(app_id), 38 weak_ptr_factory_(this) { 39} 40 41RegisterAppTask::~RegisterAppTask() { 42} 43 44void RegisterAppTask::Run(const SyncStatusCallback& callback) { 45 if (create_folder_retry_count_++ >= kMaxRetry) { 46 callback.Run(SYNC_STATUS_FAILED); 47 return; 48 } 49 50 if (!metadata_database() || !drive_service()) { 51 callback.Run(SYNC_STATUS_FAILED); 52 return; 53 } 54 55 int64 sync_root = metadata_database()->GetSyncRootTrackerID(); 56 TrackerSet trackers; 57 if (!metadata_database()->FindTrackersByParentAndTitle( 58 sync_root, app_id_, &trackers)) { 59 CreateAppRootFolder(callback); 60 return; 61 } 62 63 FileTracker candidate; 64 if (!FilterCandidates(trackers, &candidate)) { 65 CreateAppRootFolder(callback); 66 return; 67 } 68 69 if (candidate.active()) { 70 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); 71 return; 72 } 73 74 RegisterAppIntoDatabase(candidate, callback); 75} 76 77void RegisterAppTask::CreateAppRootFolder(const SyncStatusCallback& callback) { 78 int64 sync_root_tracker_id = metadata_database()->GetSyncRootTrackerID(); 79 FileTracker sync_root_tracker; 80 bool should_success = metadata_database()->FindTrackerByTrackerID( 81 sync_root_tracker_id, 82 &sync_root_tracker); 83 DCHECK(should_success); 84 85 drive_service()->AddNewDirectory( 86 sync_root_tracker.file_id(), 87 app_id_, 88 base::Bind(&RegisterAppTask::DidCreateAppRootFolder, 89 weak_ptr_factory_.GetWeakPtr(), 90 callback, 91 metadata_database()->GetLargestKnownChangeID())); 92} 93 94void RegisterAppTask::DidCreateAppRootFolder( 95 const SyncStatusCallback& callback, 96 int64 change_id, 97 google_apis::GDataErrorCode error, 98 scoped_ptr<google_apis::ResourceEntry> entry) { 99 if (error != google_apis::HTTP_SUCCESS && 100 error != google_apis::HTTP_CREATED) { 101 callback.Run(SYNC_STATUS_FAILED); 102 return; 103 } 104 105 DCHECK(entry); 106 scoped_ptr<google_apis::FileResource> resource( 107 drive::util::ConvertResourceEntryToFileResource(*entry)); 108 metadata_database()->UpdateByFileResource( 109 change_id, 110 *resource, 111 base::Bind(&RegisterAppTask::DidUpdateDatabase, 112 weak_ptr_factory_.GetWeakPtr(), 113 callback, 114 resource->file_id())); 115} 116 117void RegisterAppTask::DidUpdateDatabase(const SyncStatusCallback& callback, 118 const std::string& file_id, 119 SyncStatusCode status) { 120 if (status != SYNC_STATUS_OK) { 121 callback.Run(SYNC_STATUS_FAILED); 122 return; 123 } 124 125 FileMetadata file; 126 bool should_success = metadata_database()->FindFileByFileID( 127 file_id, &file); 128 DCHECK(should_success); 129 130 TrackerSet trackers; 131 should_success = metadata_database()->FindTrackersByFileID( 132 file_id, &trackers); 133 DCHECK(should_success); 134 135 DCHECK_EQ(1u, trackers.tracker_set().size()); 136 FileTracker tracker = **trackers.begin(); 137 DCHECK_EQ(metadata_database()->GetSyncRootTrackerID(), 138 tracker.parent_tracker_id()); 139 140 metadata_database()->UpdateTracker( 141 tracker.tracker_id(), 142 file.details(), 143 base::Bind(&RegisterAppTask::DidPrepareForRegister, 144 weak_ptr_factory_.GetWeakPtr(), 145 callback)); 146} 147 148void RegisterAppTask::DidPrepareForRegister(const SyncStatusCallback& callback, 149 SyncStatusCode status) { 150 if (status != SYNC_STATUS_OK) { 151 callback.Run(SYNC_STATUS_FAILED); 152 return; 153 } 154 155 // TODO(tzik): Ensure the file didn't make create-create conflict by listing 156 // the same title folders. 157 158 Run(callback); 159} 160 161bool RegisterAppTask::FilterCandidates(const TrackerSet& trackers, 162 FileTracker* candidate) { 163 DCHECK(candidate); 164 if (trackers.has_active()) { 165 *candidate = *trackers.active_tracker(); 166 return true; 167 } 168 169 FileTracker* oldest_tracker = NULL; 170 for (TrackerSet::const_iterator itr = trackers.begin(); 171 itr != trackers.end(); ++itr) { 172 FileTracker* tracker = *itr; 173 DCHECK(!tracker->active()); 174 DCHECK(tracker->has_synced_details()); 175 if (tracker->synced_details().file_kind() != FILE_KIND_FOLDER) 176 continue; 177 178 if (tracker->synced_details().missing()) 179 continue; 180 181 if (oldest_tracker && CompareOnCTime(*oldest_tracker, *tracker)) 182 continue; 183 184 oldest_tracker = tracker; 185 } 186 187 if (!oldest_tracker) 188 return false; 189 190 *candidate = *oldest_tracker; 191 return true; 192} 193 194void RegisterAppTask::RegisterAppIntoDatabase( 195 const FileTracker& tracker, 196 const SyncStatusCallback& callback) { 197 metadata_database()->RegisterApp( 198 app_id_, tracker.file_id(), callback); 199} 200 201MetadataDatabase* RegisterAppTask::metadata_database() { 202 return sync_context_->GetMetadataDatabase(); 203} 204 205drive::DriveServiceInterface* RegisterAppTask::drive_service() { 206 return sync_context_->GetDriveService(); 207} 208 209} // namespace drive_backend 210} // namespace sync_file_system 211