Home | History | Annotate | Download | only in drive_backend
      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 <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/format_macros.h"
     11 #include "base/location.h"
     12 #include "base/strings/stringprintf.h"
     13 #include "chrome/browser/drive/drive_service_interface.h"
     14 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
     15 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
     16 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
     17 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
     18 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
     19 #include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
     20 #include "chrome/browser/sync_file_system/logger.h"
     21 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
     22 #include "google_apis/drive/drive_api_parser.h"
     23 #include "google_apis/drive/gdata_wapi_parser.h"
     24 
     25 namespace sync_file_system {
     26 namespace drive_backend {
     27 
     28 ListChangesTask::ListChangesTask(SyncEngineContext* sync_context)
     29     : sync_context_(sync_context),
     30       weak_ptr_factory_(this) {
     31 }
     32 
     33 ListChangesTask::~ListChangesTask() {
     34 }
     35 
     36 void ListChangesTask::RunPreflight(scoped_ptr<SyncTaskToken> token) {
     37   token->InitializeTaskLog("List Changes");
     38 
     39   if (!IsContextReady()) {
     40     token->RecordLog("Failed to get required service.");
     41     SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
     42     return;
     43   }
     44 
     45   SyncTaskManager::UpdateTaskBlocker(
     46       token.Pass(),
     47       scoped_ptr<TaskBlocker>(new TaskBlocker),
     48       base::Bind(&ListChangesTask::StartListing,
     49                  weak_ptr_factory_.GetWeakPtr()));
     50 }
     51 
     52 void 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 
     59 void 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     token->RecordLog("Failed to fetch change list.");
     66     SyncTaskManager::NotifyTaskDone(
     67         token.Pass(), SYNC_STATUS_NETWORK_ERROR);
     68     return;
     69   }
     70 
     71   if (!change_list) {
     72     NOTREACHED();
     73     token->RecordLog("Got invalid change list.");
     74     SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
     75     return;
     76   }
     77 
     78   std::vector<google_apis::ChangeResource*> changes;
     79   change_list->mutable_items()->release(&changes);
     80 
     81   change_list_.reserve(change_list_.size() + changes.size());
     82   for (size_t i = 0; i < changes.size(); ++i)
     83     change_list_.push_back(changes[i]);
     84 
     85   if (!change_list->next_link().is_empty()) {
     86     drive_service()->GetRemainingChangeList(
     87         change_list->next_link(),
     88         base::Bind(
     89             &ListChangesTask::DidListChanges,
     90             weak_ptr_factory_.GetWeakPtr(),
     91             base::Passed(&token)));
     92     return;
     93   }
     94 
     95   if (change_list_.empty()) {
     96     token->RecordLog("Got no change.");
     97     SyncTaskManager::NotifyTaskDone(
     98         token.Pass(), SYNC_STATUS_NO_CHANGE_TO_SYNC);
     99     return;
    100   }
    101 
    102   scoped_ptr<TaskBlocker> task_blocker(new TaskBlocker);
    103   task_blocker->exclusive = true;
    104   SyncTaskManager::UpdateTaskBlocker(
    105       token.Pass(),
    106       task_blocker.Pass(),
    107       base::Bind(&ListChangesTask::CheckInChangeList,
    108                  weak_ptr_factory_.GetWeakPtr(),
    109                  change_list->largest_change_id()));
    110 }
    111 
    112 void ListChangesTask::CheckInChangeList(int64 largest_change_id,
    113                                         scoped_ptr<SyncTaskToken> token) {
    114   token->RecordLog(base::StringPrintf(
    115       "Got %" PRIuS " changes, updating MetadataDatabase.",
    116       change_list_.size()));
    117 
    118   DCHECK(file_ids_.empty());
    119   file_ids_.reserve(change_list_.size());
    120   for (size_t i = 0; i < change_list_.size(); ++i)
    121     file_ids_.push_back(change_list_[i]->file_id());
    122 
    123   SyncStatusCode status =
    124       metadata_database()->UpdateByChangeList(
    125           largest_change_id, change_list_.Pass());
    126   if (status != SYNC_STATUS_OK) {
    127     SyncTaskManager::NotifyTaskDone(token.Pass(), status);
    128     return;
    129   }
    130 
    131   status = metadata_database()->SweepDirtyTrackers(file_ids_);
    132   SyncTaskManager::NotifyTaskDone(token.Pass(), status);
    133 }
    134 
    135 bool ListChangesTask::IsContextReady() {
    136   return sync_context_->GetMetadataDatabase() &&
    137       sync_context_->GetDriveService();
    138 }
    139 
    140 MetadataDatabase* ListChangesTask::metadata_database() {
    141   return sync_context_->GetMetadataDatabase();
    142 }
    143 
    144 drive::DriveServiceInterface* ListChangesTask::drive_service() {
    145   set_used_network(true);
    146   return sync_context_->GetDriveService();
    147 }
    148 
    149 }  // namespace drive_backend
    150 }  // namespace sync_file_system
    151