list_changes_task.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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 "chrome/browser/drive/drive_api_util.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 23namespace sync_file_system { 24namespace drive_backend { 25 26namespace { 27 28scoped_ptr<google_apis::ChangeResource> ConvertResourceEntryToChangeResource( 29 const google_apis::ResourceEntry& entry) { 30 scoped_ptr<google_apis::ChangeResource> out(new google_apis::ChangeResource); 31 out->set_file_id(entry.resource_id()); 32 if (!entry.deleted()) 33 out->set_file(drive::util::ConvertResourceEntryToFileResource(entry)); 34 out->set_change_id(entry.changestamp()); 35 out->set_deleted(entry.deleted()); 36 37 return out.Pass(); 38} 39 40} // namespace 41 42ListChangesTask::ListChangesTask(SyncEngineContext* sync_context) 43 : sync_context_(sync_context), 44 weak_ptr_factory_(this) { 45} 46 47ListChangesTask::~ListChangesTask() { 48} 49 50void ListChangesTask::RunPreflight(scoped_ptr<SyncTaskToken> token) { 51 util::Log(logging::LOG_VERBOSE, FROM_HERE, "[Changes] Start."); 52 53 if (!IsContextReady()) { 54 util::Log(logging::LOG_VERBOSE, FROM_HERE, 55 "[Changes] Failed to get required service."); 56 RunSoon(FROM_HERE, base::Bind(&SyncTaskManager::NotifyTaskDone, 57 base::Passed(&token), 58 SYNC_STATUS_FAILED)); 59 return; 60 } 61 62 SyncTaskManager::UpdateBlockingFactor( 63 token.Pass(), 64 scoped_ptr<BlockingFactor>(new BlockingFactor), 65 base::Bind(&ListChangesTask::StartListing, 66 weak_ptr_factory_.GetWeakPtr())); 67} 68 69void ListChangesTask::StartListing(scoped_ptr<SyncTaskToken> token) { 70 drive_service()->GetChangeList( 71 metadata_database()->GetLargestFetchedChangeID() + 1, 72 base::Bind(&ListChangesTask::DidListChanges, 73 weak_ptr_factory_.GetWeakPtr(), base::Passed(&token))); 74} 75 76void ListChangesTask::DidListChanges( 77 scoped_ptr<SyncTaskToken> token, 78 google_apis::GDataErrorCode error, 79 scoped_ptr<google_apis::ResourceList> resource_list) { 80 SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error); 81 if (status != SYNC_STATUS_OK) { 82 util::Log(logging::LOG_VERBOSE, FROM_HERE, 83 "[Changes] Failed to fetch change list."); 84 SyncTaskManager::NotifyTaskDone( 85 token.Pass(), SYNC_STATUS_NETWORK_ERROR); 86 return; 87 } 88 89 if (!resource_list) { 90 NOTREACHED(); 91 util::Log(logging::LOG_VERBOSE, FROM_HERE, 92 "[Changes] Got invalid change list."); 93 SyncTaskManager::NotifyTaskDone( 94 token.Pass(), SYNC_STATUS_FAILED); 95 return; 96 } 97 98 change_list_.reserve(change_list_.size() + resource_list->entries().size()); 99 for (size_t i = 0; i < resource_list->entries().size(); ++i) { 100 change_list_.push_back(ConvertResourceEntryToChangeResource( 101 *resource_list->entries()[i]).release()); 102 } 103 104 GURL next_feed; 105 if (resource_list->GetNextFeedURL(&next_feed)) { 106 drive_service()->GetRemainingChangeList( 107 next_feed, 108 base::Bind( 109 &ListChangesTask::DidListChanges, 110 weak_ptr_factory_.GetWeakPtr(), 111 base::Passed(&token))); 112 return; 113 } 114 115 if (change_list_.empty()) { 116 util::Log(logging::LOG_VERBOSE, FROM_HERE, "[Changes] Got no change."); 117 SyncTaskManager::NotifyTaskDone( 118 token.Pass(), SYNC_STATUS_NO_CHANGE_TO_SYNC); 119 return; 120 } 121 122 scoped_ptr<BlockingFactor> blocking_factor(new BlockingFactor); 123 blocking_factor->exclusive = true; 124 SyncTaskManager::UpdateBlockingFactor( 125 token.Pass(), 126 blocking_factor.Pass(), 127 base::Bind(&ListChangesTask::CheckInChangeList, 128 weak_ptr_factory_.GetWeakPtr(), 129 resource_list->largest_changestamp())); 130} 131 132void ListChangesTask::CheckInChangeList(int64 largest_change_id, 133 scoped_ptr<SyncTaskToken> token) { 134 util::Log(logging::LOG_VERBOSE, FROM_HERE, 135 "[Changes] Got %" PRIuS " changes, updating MetadataDatabase.", 136 change_list_.size()); 137 metadata_database()->UpdateByChangeList( 138 largest_change_id, 139 change_list_.Pass(), 140 base::Bind(&SyncTaskManager::NotifyTaskDone, base::Passed(&token))); 141} 142 143bool ListChangesTask::IsContextReady() { 144 return sync_context_->GetMetadataDatabase() && 145 sync_context_->GetDriveService(); 146} 147 148MetadataDatabase* ListChangesTask::metadata_database() { 149 return sync_context_->GetMetadataDatabase(); 150} 151 152drive::DriveServiceInterface* ListChangesTask::drive_service() { 153 set_used_network(true); 154 return sync_context_->GetDriveService(); 155} 156 157} // namespace drive_backend 158} // namespace sync_file_system 159