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