list_changes_task.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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
23namespace sync_file_system {
24namespace drive_backend {
25
26ListChangesTask::ListChangesTask(SyncEngineContext* sync_context)
27    : sync_context_(sync_context),
28      weak_ptr_factory_(this) {
29}
30
31ListChangesTask::~ListChangesTask() {
32}
33
34void 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
50void 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
57void 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
110void 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
122bool ListChangesTask::IsContextReady() {
123  return sync_context_->GetMetadataDatabase() &&
124      sync_context_->GetDriveService();
125}
126
127MetadataDatabase* ListChangesTask::metadata_database() {
128  return sync_context_->GetMetadataDatabase();
129}
130
131drive::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