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.
5 #include "chrome/browser/sync_file_system/drive_backend/register_app_task.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"
21 namespace sync_file_system {
22 namespace drive_backend {
26 bool CompareOnCTime(const FileTracker& left,
27 const FileTracker& right) {
28 return left.synced_details().creation_time() <
29 right.synced_details().creation_time();
34 RegisterAppTask::RegisterAppTask(SyncEngineContext* sync_context,
35 const std::string& app_id)
36 : sync_context_(sync_context),
37 create_folder_retry_count_(0),
39 weak_ptr_factory_(this) {
42 RegisterAppTask::~RegisterAppTask() {
45 bool RegisterAppTask::CanFinishImmediately() {
46 return metadata_database() &&
47 metadata_database()->FindAppRootTracker(app_id_, nullptr);
50 void RegisterAppTask::RunExclusive(const SyncStatusCallback& callback) {
51 if (create_folder_retry_count_++ >= kMaxRetry) {
52 callback.Run(SYNC_STATUS_FAILED);
56 if (!metadata_database() || !drive_service()) {
57 callback.Run(SYNC_STATUS_FAILED);
61 int64 sync_root = metadata_database()->GetSyncRootTrackerID();
62 TrackerIDSet trackers;
63 if (!metadata_database()->FindTrackersByParentAndTitle(
64 sync_root, app_id_, &trackers)) {
65 CreateAppRootFolder(callback);
69 FileTracker candidate;
70 if (!FilterCandidates(trackers, &candidate)) {
71 CreateAppRootFolder(callback);
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);
82 RegisterAppIntoDatabase(candidate, callback);
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(
91 DCHECK(should_success);
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));
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);
112 RunExclusive(callback);
115 bool RegisterAppTask::FilterCandidates(const TrackerIDSet& trackers,
116 FileTracker* candidate) {
118 if (trackers.has_active()) {
119 if (metadata_database()->FindTrackerByTrackerID(
120 trackers.active_tracker(), candidate)) {
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())) {
137 DCHECK(!tracker->active());
138 DCHECK(tracker->has_synced_details());
140 if (!metadata_database()->FindFileByFileID(tracker->file_id(), &file)) {
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
149 if (file.details().file_kind() != FILE_KIND_FOLDER)
152 if (file.details().missing())
155 if (oldest_tracker && CompareOnCTime(*oldest_tracker, *tracker))
158 oldest_tracker = tracker.Pass();
164 *candidate = *oldest_tracker;
168 void RegisterAppTask::RegisterAppIntoDatabase(
169 const FileTracker& tracker,
170 const SyncStatusCallback& callback) {
171 SyncStatusCode status =
172 metadata_database()->RegisterApp(app_id_, tracker.file_id());
173 callback.Run(status);
176 MetadataDatabase* RegisterAppTask::metadata_database() {
177 return sync_context_->GetMetadataDatabase();
180 drive::DriveServiceInterface* RegisterAppTask::drive_service() {
181 return sync_context_->GetDriveService();
184 } // namespace drive_backend
185 } // namespace sync_file_system