Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / drive_backend / register_app_task.cc
blobcc2249be4370db900c27e462f3b38bcc17cf55ce
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"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
10 #include "chrome/browser/sync_file_system/drive_backend/folder_creator.h"
11 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
12 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
13 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
14 #include "chrome/browser/sync_file_system/drive_backend/tracker_id_set.h"
15 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
16 #include "components/drive/drive_api_util.h"
17 #include "components/drive/service/drive_service_interface.h"
18 #include "google_apis/drive/drive_api_parser.h"
20 namespace sync_file_system {
21 namespace drive_backend {
23 namespace {
25 bool CompareOnCTime(const FileTracker& left,
26 const FileTracker& right) {
27 return left.synced_details().creation_time() <
28 right.synced_details().creation_time();
31 } // namespace
33 RegisterAppTask::RegisterAppTask(SyncEngineContext* sync_context,
34 const std::string& app_id)
35 : sync_context_(sync_context),
36 create_folder_retry_count_(0),
37 app_id_(app_id),
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);
52 return;
55 if (!metadata_database() || !drive_service()) {
56 callback.Run(SYNC_STATUS_FAILED);
57 return;
60 int64 sync_root = metadata_database()->GetSyncRootTrackerID();
61 TrackerIDSet trackers;
62 if (!metadata_database()->FindTrackersByParentAndTitle(
63 sync_root, app_id_, &trackers)) {
64 CreateAppRootFolder(callback);
65 return;
68 FileTracker candidate;
69 if (!FilterCandidates(trackers, &candidate)) {
70 CreateAppRootFolder(callback);
71 return;
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);
78 return;
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(
88 sync_root_tracker_id,
89 &sync_root_tracker);
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);
108 return;
111 RunExclusive(callback);
114 bool RegisterAppTask::FilterCandidates(const TrackerIDSet& trackers,
115 FileTracker* candidate) {
116 DCHECK(candidate);
117 if (trackers.has_active()) {
118 if (metadata_database()->FindTrackerByTrackerID(
119 trackers.active_tracker(), candidate)) {
120 return true;
122 NOTREACHED();
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())) {
131 NOTREACHED();
132 continue;
135 FileMetadata file;
136 DCHECK(!tracker->active());
137 DCHECK(tracker->has_synced_details());
139 if (!metadata_database()->FindFileByFileID(tracker->file_id(), &file)) {
140 NOTREACHED();
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
144 // FileMetadata.
145 continue;
148 if (file.details().file_kind() != FILE_KIND_FOLDER)
149 continue;
151 if (file.details().missing())
152 continue;
154 if (oldest_tracker && CompareOnCTime(*oldest_tracker, *tracker))
155 continue;
157 oldest_tracker = tracker.Pass();
160 if (!oldest_tracker)
161 return false;
163 *candidate = *oldest_tracker;
164 return true;
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