Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / drive_backend / register_app_task.cc
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::RunSequential(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     RunSoon(FROM_HERE, base::Bind(callback, 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   RunSequential(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