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"
20 namespace sync_file_system
{
21 namespace drive_backend
{
25 bool CompareOnCTime(const FileTracker
& left
,
26 const FileTracker
& right
) {
27 return left
.synced_details().creation_time() <
28 right
.synced_details().creation_time();
33 RegisterAppTask::RegisterAppTask(SyncEngineContext
* sync_context
,
34 const std::string
& app_id
)
35 : sync_context_(sync_context
),
36 create_folder_retry_count_(0),
38 weak_ptr_factory_(this) {
41 RegisterAppTask::~RegisterAppTask() {
44 bool RegisterAppTask::CanFinishImmediately() {
45 return metadata_database() &&
46 metadata_database()->FindAppRootTracker(app_id_
, nullptr);
49 void RegisterAppTask::RunExclusive(const SyncStatusCallback
& callback
) {
50 if (create_folder_retry_count_
++ >= kMaxRetry
) {
51 callback
.Run(SYNC_STATUS_FAILED
);
55 if (!metadata_database() || !drive_service()) {
56 callback
.Run(SYNC_STATUS_FAILED
);
60 int64 sync_root
= metadata_database()->GetSyncRootTrackerID();
61 TrackerIDSet trackers
;
62 if (!metadata_database()->FindTrackersByParentAndTitle(
63 sync_root
, app_id_
, &trackers
)) {
64 CreateAppRootFolder(callback
);
68 FileTracker candidate
;
69 if (!FilterCandidates(trackers
, &candidate
)) {
70 CreateAppRootFolder(callback
);
74 if (candidate
.active()) {
75 DCHECK(candidate
.tracker_kind() == TRACKER_KIND_APP_ROOT
||
76 candidate
.tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT
);
77 callback
.Run(SYNC_STATUS_OK
);
81 RegisterAppIntoDatabase(candidate
, callback
);
84 void RegisterAppTask::CreateAppRootFolder(const SyncStatusCallback
& callback
) {
85 int64 sync_root_tracker_id
= metadata_database()->GetSyncRootTrackerID();
86 FileTracker sync_root_tracker
;
87 bool should_success
= metadata_database()->FindTrackerByTrackerID(
90 DCHECK(should_success
);
92 DCHECK(!folder_creator_
);
93 folder_creator_
.reset(new FolderCreator(
94 drive_service(), metadata_database(),
95 sync_root_tracker
.file_id(), app_id_
));
96 folder_creator_
->Run(base::Bind(
97 &RegisterAppTask::DidCreateAppRootFolder
,
98 weak_ptr_factory_
.GetWeakPtr(), callback
));
101 void RegisterAppTask::DidCreateAppRootFolder(
102 const SyncStatusCallback
& callback
,
103 const std::string
& folder_id
,
104 SyncStatusCode status
) {
105 scoped_ptr
<FolderCreator
> deleter
= folder_creator_
.Pass();
106 if (status
!= SYNC_STATUS_OK
) {
107 callback
.Run(status
);
111 RunExclusive(callback
);
114 bool RegisterAppTask::FilterCandidates(const TrackerIDSet
& trackers
,
115 FileTracker
* candidate
) {
117 if (trackers
.has_active()) {
118 if (metadata_database()->FindTrackerByTrackerID(
119 trackers
.active_tracker(), candidate
)) {
125 scoped_ptr
<FileTracker
> oldest_tracker
;
126 for (TrackerIDSet::const_iterator itr
= trackers
.begin();
127 itr
!= trackers
.end(); ++itr
) {
128 scoped_ptr
<FileTracker
> tracker(new FileTracker
);
129 if (!metadata_database()->FindTrackerByTrackerID(
130 *itr
, tracker
.get())) {
136 DCHECK(!tracker
->active());
137 DCHECK(tracker
->has_synced_details());
139 if (!metadata_database()->FindFileByFileID(tracker
->file_id(), &file
)) {
141 // The parent folder is sync-root, whose contents are fetched in
142 // initialization sequence.
143 // So at this point, direct children of sync-root should have
148 if (file
.details().file_kind() != FILE_KIND_FOLDER
)
151 if (file
.details().missing())
154 if (oldest_tracker
&& CompareOnCTime(*oldest_tracker
, *tracker
))
157 oldest_tracker
= tracker
.Pass();
163 *candidate
= *oldest_tracker
;
167 void RegisterAppTask::RegisterAppIntoDatabase(
168 const FileTracker
& tracker
,
169 const SyncStatusCallback
& callback
) {
170 SyncStatusCode status
=
171 metadata_database()->RegisterApp(app_id_
, tracker
.file_id());
172 callback
.Run(status
);
175 MetadataDatabase
* RegisterAppTask::metadata_database() {
176 return sync_context_
->GetMetadataDatabase();
179 drive::DriveServiceInterface
* RegisterAppTask::drive_service() {
180 return sync_context_
->GetDriveService();
183 } // namespace drive_backend
184 } // namespace sync_file_system