list_changes_task.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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/location.h"
9#include "chrome/browser/drive/drive_api_util.h"
10#include "chrome/browser/drive/drive_service_interface.h"
11#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
12#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
13#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
14#include "chrome/browser/sync_file_system/logger.h"
15#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
16#include "google_apis/drive/drive_api_parser.h"
17#include "google_apis/drive/gdata_wapi_parser.h"
18
19namespace sync_file_system {
20namespace drive_backend {
21
22namespace {
23
24scoped_ptr<google_apis::ChangeResource> ConvertResourceEntryToChangeResource(
25    const google_apis::ResourceEntry& entry) {
26  scoped_ptr<google_apis::ChangeResource> out(new google_apis::ChangeResource);
27  out->set_file_id(entry.resource_id());
28  if (!entry.deleted())
29    out->set_file(drive::util::ConvertResourceEntryToFileResource(entry));
30  out->set_change_id(entry.changestamp());
31  out->set_deleted(entry.deleted());
32
33  return out.Pass();
34}
35
36}  // namespace
37
38ListChangesTask::ListChangesTask(SyncEngineContext* sync_context)
39    : sync_context_(sync_context),
40      weak_ptr_factory_(this) {
41}
42
43ListChangesTask::~ListChangesTask() {
44}
45
46void ListChangesTask::Run(const SyncStatusCallback& callback) {
47  if (!IsContextReady()) {
48    util::Log(logging::LOG_ERROR, FROM_HERE, "Failed to get required sercive.");
49    RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_FAILED));
50    return;
51  }
52
53  drive_service()->GetChangeList(
54      metadata_database()->GetLargestFetchedChangeID() + 1,
55      base::Bind(&ListChangesTask::DidListChanges,
56                 weak_ptr_factory_.GetWeakPtr(), callback));
57}
58
59void ListChangesTask::DidListChanges(
60    const SyncStatusCallback& callback,
61    google_apis::GDataErrorCode error,
62    scoped_ptr<google_apis::ResourceList> resource_list) {
63  if (error != google_apis::HTTP_SUCCESS) {
64    util::Log(logging::LOG_ERROR, FROM_HERE, "Failed to fetch change list.");
65    callback.Run(SYNC_STATUS_NETWORK_ERROR);
66    return;
67  }
68
69  change_list_.reserve(change_list_.size() + resource_list->entries().size());
70  for (size_t i = 0; i < resource_list->entries().size(); ++i) {
71    change_list_.push_back(ConvertResourceEntryToChangeResource(
72        *resource_list->entries()[i]).release());
73  }
74
75  // TODO(tzik): http://crbug.com/310964
76  // This may take long time to run in single task.  Run this as a background
77  // task.
78  GURL next_feed;
79  if (resource_list->GetNextFeedURL(&next_feed)) {
80    drive_service()->GetRemainingChangeList(
81        next_feed,
82        base::Bind(
83            &ListChangesTask::DidListChanges,
84            weak_ptr_factory_.GetWeakPtr(),
85            callback));
86    return;
87  }
88
89  if (change_list_.empty()) {
90    callback.Run(SYNC_STATUS_NO_CHANGE_TO_SYNC);
91    return;
92  }
93
94  metadata_database()->UpdateByChangeList(
95      resource_list->largest_changestamp(),
96      change_list_.Pass(), callback);
97}
98
99bool ListChangesTask::IsContextReady() {
100  return sync_context_->GetMetadataDatabase() &&
101      sync_context_->GetDriveService();
102}
103
104MetadataDatabase* ListChangesTask::metadata_database() {
105  return sync_context_->GetMetadataDatabase();
106}
107
108drive::DriveServiceInterface* ListChangesTask::drive_service() {
109  set_used_network(true);
110  return sync_context_->GetDriveService();
111}
112
113}  // namespace drive_backend
114}  // namespace sync_file_system
115