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