list_changes_task.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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_service_interface.h"
11#include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
12#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
13#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
14#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
15#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
16#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
17#include "chrome/browser/sync_file_system/logger.h"
18#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
19#include "google_apis/drive/drive_api_parser.h"
20#include "google_apis/drive/gdata_wapi_parser.h"
21
22namespace sync_file_system {
23namespace drive_backend {
24
25ListChangesTask::ListChangesTask(SyncEngineContext* sync_context)
26    : sync_context_(sync_context),
27      weak_ptr_factory_(this) {
28}
29
30ListChangesTask::~ListChangesTask() {
31}
32
33void ListChangesTask::RunPreflight(scoped_ptr<SyncTaskToken> token) {
34  util::Log(logging::LOG_VERBOSE, FROM_HERE, "[Changes] Start.");
35
36  if (!IsContextReady()) {
37    util::Log(logging::LOG_VERBOSE, FROM_HERE,
38              "[Changes] Failed to get required service.");
39    RunSoon(FROM_HERE, base::Bind(&SyncTaskManager::NotifyTaskDone,
40                                  base::Passed(&token),
41                                  SYNC_STATUS_FAILED));
42    return;
43  }
44
45  SyncTaskManager::UpdateBlockingFactor(
46      token.Pass(),
47      scoped_ptr<BlockingFactor>(new BlockingFactor),
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    util::Log(logging::LOG_VERBOSE, FROM_HERE,
66              "[Changes] Failed to fetch change list.");
67    SyncTaskManager::NotifyTaskDone(
68        token.Pass(), SYNC_STATUS_NETWORK_ERROR);
69    return;
70  }
71
72  if (!change_list) {
73    NOTREACHED();
74    util::Log(logging::LOG_VERBOSE, FROM_HERE,
75              "[Changes] Got invalid change list.");
76    SyncTaskManager::NotifyTaskDone(
77        token.Pass(), SYNC_STATUS_FAILED);
78    return;
79  }
80
81  std::vector<google_apis::ChangeResource*> changes;
82  change_list->mutable_items()->release(&changes);
83
84  change_list_.reserve(change_list_.size() + changes.size());
85  for (size_t i = 0; i < changes.size(); ++i)
86    change_list_.push_back(changes[i]);
87
88  if (!change_list->next_link().is_empty()) {
89    drive_service()->GetRemainingChangeList(
90        change_list->next_link(),
91        base::Bind(
92            &ListChangesTask::DidListChanges,
93            weak_ptr_factory_.GetWeakPtr(),
94            base::Passed(&token)));
95    return;
96  }
97
98  if (change_list_.empty()) {
99    util::Log(logging::LOG_VERBOSE, FROM_HERE, "[Changes] Got no change.");
100    SyncTaskManager::NotifyTaskDone(
101        token.Pass(), SYNC_STATUS_NO_CHANGE_TO_SYNC);
102    return;
103  }
104
105  scoped_ptr<BlockingFactor> blocking_factor(new BlockingFactor);
106  blocking_factor->exclusive = true;
107  SyncTaskManager::UpdateBlockingFactor(
108      token.Pass(),
109      blocking_factor.Pass(),
110      base::Bind(&ListChangesTask::CheckInChangeList,
111                 weak_ptr_factory_.GetWeakPtr(),
112                 change_list->largest_change_id()));
113}
114
115void ListChangesTask::CheckInChangeList(int64 largest_change_id,
116                                        scoped_ptr<SyncTaskToken> token) {
117  util::Log(logging::LOG_VERBOSE, FROM_HERE,
118            "[Changes] Got %" PRIuS " changes, updating MetadataDatabase.",
119            change_list_.size());
120  metadata_database()->UpdateByChangeList(
121      largest_change_id,
122      change_list_.Pass(),
123      base::Bind(&SyncTaskManager::NotifyTaskDone, base::Passed(&token)));
124}
125
126bool ListChangesTask::IsContextReady() {
127  return sync_context_->GetMetadataDatabase() &&
128      sync_context_->GetDriveService();
129}
130
131MetadataDatabase* ListChangesTask::metadata_database() {
132  return sync_context_->GetMetadataDatabase();
133}
134
135drive::DriveServiceInterface* ListChangesTask::drive_service() {
136  set_used_network(true);
137  return sync_context_->GetDriveService();
138}
139
140}  // namespace drive_backend
141}  // namespace sync_file_system
142