register_app_task.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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/sync_file_system/drive_backend/drive_backend_constants.h" 12#include "chrome/browser/sync_file_system/drive_backend/folder_creator.h" 13#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 14#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" 15#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 16#include "chrome/browser/sync_file_system/drive_backend/tracker_set.h" 17#include "chrome/browser/sync_file_system/syncable_file_system_util.h" 18#include "google_apis/drive/drive_api_parser.h" 19#include "google_apis/drive/gdata_wapi_parser.h" 20 21namespace sync_file_system { 22namespace drive_backend { 23 24namespace { 25 26bool CompareOnCTime(const FileTracker& left, 27 const FileTracker& right) { 28 return left.synced_details().creation_time() < 29 right.synced_details().creation_time(); 30} 31 32} // namespace 33 34RegisterAppTask::RegisterAppTask(SyncEngineContext* sync_context, 35 const std::string& app_id) 36 : sync_context_(sync_context), 37 create_folder_retry_count_(0), 38 app_id_(app_id), 39 weak_ptr_factory_(this) { 40} 41 42RegisterAppTask::~RegisterAppTask() { 43} 44 45void RegisterAppTask::Run(const SyncStatusCallback& callback) { 46 if (create_folder_retry_count_++ >= kMaxRetry) { 47 callback.Run(SYNC_STATUS_FAILED); 48 return; 49 } 50 51 if (!metadata_database() || !drive_service()) { 52 callback.Run(SYNC_STATUS_FAILED); 53 return; 54 } 55 56 int64 sync_root = metadata_database()->GetSyncRootTrackerID(); 57 TrackerSet trackers; 58 if (!metadata_database()->FindTrackersByParentAndTitle( 59 sync_root, app_id_, &trackers)) { 60 CreateAppRootFolder(callback); 61 return; 62 } 63 64 FileTracker candidate; 65 if (!FilterCandidates(trackers, &candidate)) { 66 CreateAppRootFolder(callback); 67 return; 68 } 69 70 if (candidate.active()) { 71 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); 72 return; 73 } 74 75 RegisterAppIntoDatabase(candidate, callback); 76} 77 78void RegisterAppTask::CreateAppRootFolder(const SyncStatusCallback& callback) { 79 int64 sync_root_tracker_id = metadata_database()->GetSyncRootTrackerID(); 80 FileTracker sync_root_tracker; 81 bool should_success = metadata_database()->FindTrackerByTrackerID( 82 sync_root_tracker_id, 83 &sync_root_tracker); 84 DCHECK(should_success); 85 86 DCHECK(!folder_creator_); 87 folder_creator_.reset(new FolderCreator( 88 drive_service(), metadata_database(), 89 sync_root_tracker.file_id(), app_id_)); 90 folder_creator_->Run(base::Bind( 91 &RegisterAppTask::DidCreateAppRootFolder, 92 weak_ptr_factory_.GetWeakPtr(), callback)); 93} 94 95void RegisterAppTask::DidCreateAppRootFolder( 96 const SyncStatusCallback& callback, 97 const std::string& folder_id, 98 SyncStatusCode status) { 99 scoped_ptr<FolderCreator> deleter = folder_creator_.Pass(); 100 if (status != SYNC_STATUS_OK) { 101 callback.Run(status); 102 return; 103 } 104 105 Run(callback); 106} 107 108bool RegisterAppTask::FilterCandidates(const TrackerSet& trackers, 109 FileTracker* candidate) { 110 DCHECK(candidate); 111 if (trackers.has_active()) { 112 *candidate = *trackers.active_tracker(); 113 return true; 114 } 115 116 FileTracker* oldest_tracker = NULL; 117 for (TrackerSet::const_iterator itr = trackers.begin(); 118 itr != trackers.end(); ++itr) { 119 FileTracker* tracker = *itr; 120 FileMetadata file; 121 DCHECK(!tracker->active()); 122 DCHECK(tracker->has_synced_details()); 123 124 if (!metadata_database()->FindFileByFileID(tracker->file_id(), &file)) { 125 NOTREACHED(); 126 // The parent folder is sync-root, whose contents are fetched in 127 // initialization sequence. 128 // So at this point, direct children of sync-root should have 129 // FileMetadata. 130 continue; 131 } 132 133 if (file.details().file_kind() != FILE_KIND_FOLDER) 134 continue; 135 136 if (file.details().missing()) 137 continue; 138 139 if (oldest_tracker && CompareOnCTime(*oldest_tracker, *tracker)) 140 continue; 141 142 oldest_tracker = tracker; 143 } 144 145 if (!oldest_tracker) 146 return false; 147 148 *candidate = *oldest_tracker; 149 return true; 150} 151 152void RegisterAppTask::RegisterAppIntoDatabase( 153 const FileTracker& tracker, 154 const SyncStatusCallback& callback) { 155 metadata_database()->RegisterApp( 156 app_id_, tracker.file_id(), callback); 157} 158 159MetadataDatabase* RegisterAppTask::metadata_database() { 160 return sync_context_->GetMetadataDatabase(); 161} 162 163drive::DriveServiceInterface* RegisterAppTask::drive_service() { 164 return sync_context_->GetDriveService(); 165} 166 167} // namespace drive_backend 168} // namespace sync_file_system 169