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/list_changes_task.h" 6 7 #include "base/bind.h" 8 #include "base/format_macros.h" 9 #include "base/location.h" 10 #include "base/strings/stringprintf.h" 11 #include "chrome/browser/drive/drive_service_interface.h" 12 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.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/sync_task_manager.h" 17 #include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h" 18 #include "chrome/browser/sync_file_system/logger.h" 19 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" 20 #include "google_apis/drive/drive_api_parser.h" 21 #include "google_apis/drive/gdata_wapi_parser.h" 22 23 namespace sync_file_system { 24 namespace drive_backend { 25 26 ListChangesTask::ListChangesTask(SyncEngineContext* sync_context) 27 : sync_context_(sync_context), 28 weak_ptr_factory_(this) { 29 } 30 31 ListChangesTask::~ListChangesTask() { 32 } 33 34 void ListChangesTask::RunPreflight(scoped_ptr<SyncTaskToken> token) { 35 token->InitializeTaskLog("List Changes"); 36 37 if (!IsContextReady()) { 38 token->RecordLog("Failed to get required service."); 39 SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); 40 return; 41 } 42 43 SyncTaskManager::UpdateBlockingFactor( 44 token.Pass(), 45 scoped_ptr<BlockingFactor>(new BlockingFactor), 46 base::Bind(&ListChangesTask::StartListing, 47 weak_ptr_factory_.GetWeakPtr())); 48 } 49 50 void ListChangesTask::StartListing(scoped_ptr<SyncTaskToken> token) { 51 drive_service()->GetChangeList( 52 metadata_database()->GetLargestFetchedChangeID() + 1, 53 base::Bind(&ListChangesTask::DidListChanges, 54 weak_ptr_factory_.GetWeakPtr(), base::Passed(&token))); 55 } 56 57 void ListChangesTask::DidListChanges( 58 scoped_ptr<SyncTaskToken> token, 59 google_apis::GDataErrorCode error, 60 scoped_ptr<google_apis::ChangeList> change_list) { 61 SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error); 62 if (status != SYNC_STATUS_OK) { 63 token->RecordLog("Failed to fetch change list."); 64 SyncTaskManager::NotifyTaskDone( 65 token.Pass(), SYNC_STATUS_NETWORK_ERROR); 66 return; 67 } 68 69 if (!change_list) { 70 NOTREACHED(); 71 token->RecordLog("Got invalid change list."); 72 SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); 73 return; 74 } 75 76 std::vector<google_apis::ChangeResource*> changes; 77 change_list->mutable_items()->release(&changes); 78 79 change_list_.reserve(change_list_.size() + changes.size()); 80 for (size_t i = 0; i < changes.size(); ++i) 81 change_list_.push_back(changes[i]); 82 83 if (!change_list->next_link().is_empty()) { 84 drive_service()->GetRemainingChangeList( 85 change_list->next_link(), 86 base::Bind( 87 &ListChangesTask::DidListChanges, 88 weak_ptr_factory_.GetWeakPtr(), 89 base::Passed(&token))); 90 return; 91 } 92 93 if (change_list_.empty()) { 94 token->RecordLog("Got no change."); 95 SyncTaskManager::NotifyTaskDone( 96 token.Pass(), SYNC_STATUS_NO_CHANGE_TO_SYNC); 97 return; 98 } 99 100 scoped_ptr<BlockingFactor> blocking_factor(new BlockingFactor); 101 blocking_factor->exclusive = true; 102 SyncTaskManager::UpdateBlockingFactor( 103 token.Pass(), 104 blocking_factor.Pass(), 105 base::Bind(&ListChangesTask::CheckInChangeList, 106 weak_ptr_factory_.GetWeakPtr(), 107 change_list->largest_change_id())); 108 } 109 110 void ListChangesTask::CheckInChangeList(int64 largest_change_id, 111 scoped_ptr<SyncTaskToken> token) { 112 token->RecordLog(base::StringPrintf( 113 "Got %" PRIuS " changes, updating MetadataDatabase.", 114 change_list_.size())); 115 116 metadata_database()->UpdateByChangeList( 117 largest_change_id, 118 change_list_.Pass(), 119 base::Bind(&SyncTaskManager::NotifyTaskDone, base::Passed(&token))); 120 } 121 122 bool ListChangesTask::IsContextReady() { 123 return sync_context_->GetMetadataDatabase() && 124 sync_context_->GetDriveService(); 125 } 126 127 MetadataDatabase* ListChangesTask::metadata_database() { 128 return sync_context_->GetMetadataDatabase(); 129 } 130 131 drive::DriveServiceInterface* ListChangesTask::drive_service() { 132 set_used_network(true); 133 return sync_context_->GetDriveService(); 134 } 135 136 } // namespace drive_backend 137 } // namespace sync_file_system 138