blob: c6273d2cc8dfc00182c431b74ecc575a27903a12 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h"
#include "base/bind.h"
#include "base/format_macros.h"
#include "base/location.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/drive/drive_service_interface.h"
#include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
#include "chrome/browser/sync_file_system/logger.h"
#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
#include "google_apis/drive/drive_api_parser.h"
#include "google_apis/drive/gdata_wapi_parser.h"
namespace sync_file_system {
namespace drive_backend {
ListChangesTask::ListChangesTask(SyncEngineContext* sync_context)
: sync_context_(sync_context),
weak_ptr_factory_(this) {
}
ListChangesTask::~ListChangesTask() {
}
void ListChangesTask::RunPreflight(scoped_ptr<SyncTaskToken> token) {
token->InitializeTaskLog("List Changes");
if (!IsContextReady()) {
token->RecordLog("Failed to get required service.");
SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
return;
}
SyncTaskManager::UpdateBlockingFactor(
token.Pass(),
scoped_ptr<BlockingFactor>(new BlockingFactor),
base::Bind(&ListChangesTask::StartListing,
weak_ptr_factory_.GetWeakPtr()));
}
void ListChangesTask::StartListing(scoped_ptr<SyncTaskToken> token) {
drive_service()->GetChangeList(
metadata_database()->GetLargestFetchedChangeID() + 1,
base::Bind(&ListChangesTask::DidListChanges,
weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
}
void ListChangesTask::DidListChanges(
scoped_ptr<SyncTaskToken> token,
google_apis::GDataErrorCode error,
scoped_ptr<google_apis::ChangeList> change_list) {
SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
if (status != SYNC_STATUS_OK) {
token->RecordLog("Failed to fetch change list.");
SyncTaskManager::NotifyTaskDone(
token.Pass(), SYNC_STATUS_NETWORK_ERROR);
return;
}
if (!change_list) {
NOTREACHED();
token->RecordLog("Got invalid change list.");
SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
return;
}
std::vector<google_apis::ChangeResource*> changes;
change_list->mutable_items()->release(&changes);
change_list_.reserve(change_list_.size() + changes.size());
for (size_t i = 0; i < changes.size(); ++i)
change_list_.push_back(changes[i]);
if (!change_list->next_link().is_empty()) {
drive_service()->GetRemainingChangeList(
change_list->next_link(),
base::Bind(
&ListChangesTask::DidListChanges,
weak_ptr_factory_.GetWeakPtr(),
base::Passed(&token)));
return;
}
if (change_list_.empty()) {
token->RecordLog("Got no change.");
SyncTaskManager::NotifyTaskDone(
token.Pass(), SYNC_STATUS_NO_CHANGE_TO_SYNC);
return;
}
scoped_ptr<BlockingFactor> blocking_factor(new BlockingFactor);
blocking_factor->exclusive = true;
SyncTaskManager::UpdateBlockingFactor(
token.Pass(),
blocking_factor.Pass(),
base::Bind(&ListChangesTask::CheckInChangeList,
weak_ptr_factory_.GetWeakPtr(),
change_list->largest_change_id()));
}
void ListChangesTask::CheckInChangeList(int64 largest_change_id,
scoped_ptr<SyncTaskToken> token) {
token->RecordLog(base::StringPrintf(
"Got %" PRIuS " changes, updating MetadataDatabase.",
change_list_.size()));
DCHECK(file_ids_.empty());
file_ids_.reserve(change_list_.size());
for (size_t i = 0; i < change_list_.size(); ++i)
file_ids_.push_back(change_list_[i]->file_id());
metadata_database()->UpdateByChangeList(
largest_change_id,
change_list_.Pass(),
base::Bind(&ListChangesTask::DidCheckInChangeList,
weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
}
void ListChangesTask::DidCheckInChangeList(scoped_ptr<SyncTaskToken> token,
SyncStatusCode status) {
if (status != SYNC_STATUS_OK) {
SyncTaskManager::NotifyTaskDone(token.Pass(), status);
return;
}
metadata_database()->SweepDirtyTrackers(
file_ids_,
base::Bind(&SyncTaskManager::NotifyTaskDone, base::Passed(&token)));
}
bool ListChangesTask::IsContextReady() {
return sync_context_->GetMetadataDatabase() &&
sync_context_->GetDriveService();
}
MetadataDatabase* ListChangesTask::metadata_database() {
return sync_context_->GetMetadataDatabase();
}
drive::DriveServiceInterface* ListChangesTask::drive_service() {
set_used_network(true);
return sync_context_->GetDriveService();
}
} // namespace drive_backend
} // namespace sync_file_system