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/register_app_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/drive_backend_constants.h"
     12 #include "chrome/browser/sync_file_system/drive_backend/folder_creator.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/tracker_id_set.h"
     17 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
     18 #include "google_apis/drive/drive_api_parser.h"
     19 #include "google_apis/drive/gdata_wapi_parser.h"
     20 
     21 namespace sync_file_system {
     22 namespace drive_backend {
     23 
     24 namespace {
     25 
     26 bool CompareOnCTime(const FileTracker& left,
     27                     const FileTracker& right) {
     28   return left.synced_details().creation_time() <
     29       right.synced_details().creation_time();
     30 }
     31 
     32 }  // namespace
     33 
     34 RegisterAppTask::RegisterAppTask(SyncEngineContext* sync_context,
     35                                  const std::string& app_id)
     36     : sync_context_(sync_context),
     37       create_folder_retry_count_(0),
     38       app_id_(app_id),
     39       weak_ptr_factory_(this) {
     40 }
     41 
     42 RegisterAppTask::~RegisterAppTask() {
     43 }
     44 
     45 bool RegisterAppTask::CanFinishImmediately() {
     46   return metadata_database() &&
     47          metadata_database()->FindAppRootTracker(app_id_, NULL);
     48 }
     49 
     50 void RegisterAppTask::RunExclusive(const SyncStatusCallback& callback) {
     51   if (create_folder_retry_count_++ >= kMaxRetry) {
     52     callback.Run(SYNC_STATUS_FAILED);
     53     return;
     54   }
     55 
     56   if (!metadata_database() || !drive_service()) {
     57     callback.Run(SYNC_STATUS_FAILED);
     58     return;
     59   }
     60 
     61   int64 sync_root = metadata_database()->GetSyncRootTrackerID();
     62   TrackerIDSet trackers;
     63   if (!metadata_database()->FindTrackersByParentAndTitle(
     64           sync_root, app_id_, &trackers)) {
     65     CreateAppRootFolder(callback);
     66     return;
     67   }
     68 
     69   FileTracker candidate;
     70   if (!FilterCandidates(trackers, &candidate)) {
     71     CreateAppRootFolder(callback);
     72     return;
     73   }
     74 
     75   if (candidate.active()) {
     76     DCHECK(candidate.tracker_kind() == TRACKER_KIND_APP_ROOT ||
     77            candidate.tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT);
     78     callback.Run(SYNC_STATUS_OK);
     79     return;
     80   }
     81 
     82   RegisterAppIntoDatabase(candidate, callback);
     83 }
     84 
     85 void RegisterAppTask::CreateAppRootFolder(const SyncStatusCallback& callback) {
     86   int64 sync_root_tracker_id = metadata_database()->GetSyncRootTrackerID();
     87   FileTracker sync_root_tracker;
     88   bool should_success = metadata_database()->FindTrackerByTrackerID(
     89       sync_root_tracker_id,
     90       &sync_root_tracker);
     91   DCHECK(should_success);
     92 
     93   DCHECK(!folder_creator_);
     94   folder_creator_.reset(new FolderCreator(
     95       drive_service(), metadata_database(),
     96       sync_root_tracker.file_id(), app_id_));
     97   folder_creator_->Run(base::Bind(
     98       &RegisterAppTask::DidCreateAppRootFolder,
     99       weak_ptr_factory_.GetWeakPtr(), callback));
    100 }
    101 
    102 void RegisterAppTask::DidCreateAppRootFolder(
    103     const SyncStatusCallback& callback,
    104     const std::string& folder_id,
    105     SyncStatusCode status) {
    106   scoped_ptr<FolderCreator> deleter = folder_creator_.Pass();
    107   if (status != SYNC_STATUS_OK) {
    108     callback.Run(status);
    109     return;
    110   }
    111 
    112   RunExclusive(callback);
    113 }
    114 
    115 bool RegisterAppTask::FilterCandidates(const TrackerIDSet& trackers,
    116                                        FileTracker* candidate) {
    117   DCHECK(candidate);
    118   if (trackers.has_active()) {
    119     if (metadata_database()->FindTrackerByTrackerID(
    120             trackers.active_tracker(), candidate)) {
    121       return true;
    122     }
    123     NOTREACHED();
    124   }
    125 
    126   scoped_ptr<FileTracker> oldest_tracker;
    127   for (TrackerIDSet::const_iterator itr = trackers.begin();
    128        itr != trackers.end(); ++itr) {
    129     scoped_ptr<FileTracker> tracker(new FileTracker);
    130     if (!metadata_database()->FindTrackerByTrackerID(
    131             *itr, tracker.get())) {
    132       NOTREACHED();
    133       continue;
    134     }
    135 
    136     FileMetadata file;
    137     DCHECK(!tracker->active());
    138     DCHECK(tracker->has_synced_details());
    139 
    140     if (!metadata_database()->FindFileByFileID(tracker->file_id(), &file)) {
    141       NOTREACHED();
    142       // The parent folder is sync-root, whose contents are fetched in
    143       // initialization sequence.
    144       // So at this point, direct children of sync-root should have
    145       // FileMetadata.
    146       continue;
    147     }
    148 
    149     if (file.details().file_kind() != FILE_KIND_FOLDER)
    150       continue;
    151 
    152     if (file.details().missing())
    153       continue;
    154 
    155     if (oldest_tracker && CompareOnCTime(*oldest_tracker, *tracker))
    156       continue;
    157 
    158     oldest_tracker = tracker.Pass();
    159   }
    160 
    161   if (!oldest_tracker)
    162     return false;
    163 
    164   *candidate = *oldest_tracker;
    165   return true;
    166 }
    167 
    168 void RegisterAppTask::RegisterAppIntoDatabase(
    169     const FileTracker& tracker,
    170     const SyncStatusCallback& callback) {
    171   metadata_database()->RegisterApp(
    172       app_id_, tracker.file_id(), callback);
    173 }
    174 
    175 MetadataDatabase* RegisterAppTask::metadata_database() {
    176   return sync_context_->GetMetadataDatabase();
    177 }
    178 
    179 drive::DriveServiceInterface* RegisterAppTask::drive_service() {
    180   return sync_context_->GetDriveService();
    181 }
    182 
    183 }  // namespace drive_backend
    184 }  // namespace sync_file_system
    185