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