register_app_task.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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_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
21namespace sync_file_system {
22namespace drive_backend {
23
24namespace {
25
26bool 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
34RegisterAppTask::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
42RegisterAppTask::~RegisterAppTask() {
43}
44
45void RegisterAppTask::Run(const SyncStatusCallback& callback) {
46  if (create_folder_retry_count_++ >= kMaxRetry) {
47    callback.Run(SYNC_STATUS_FAILED);
48    return;
49  }
50
51  if (!metadata_database() || !drive_service()) {
52    callback.Run(SYNC_STATUS_FAILED);
53    return;
54  }
55
56  int64 sync_root = metadata_database()->GetSyncRootTrackerID();
57  TrackerSet trackers;
58  if (!metadata_database()->FindTrackersByParentAndTitle(
59          sync_root, app_id_, &trackers)) {
60    CreateAppRootFolder(callback);
61    return;
62  }
63
64  FileTracker candidate;
65  if (!FilterCandidates(trackers, &candidate)) {
66    CreateAppRootFolder(callback);
67    return;
68  }
69
70  if (candidate.active()) {
71    RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
72    return;
73  }
74
75  RegisterAppIntoDatabase(candidate, callback);
76}
77
78void RegisterAppTask::CreateAppRootFolder(const SyncStatusCallback& callback) {
79  int64 sync_root_tracker_id = metadata_database()->GetSyncRootTrackerID();
80  FileTracker sync_root_tracker;
81  bool should_success = metadata_database()->FindTrackerByTrackerID(
82      sync_root_tracker_id,
83      &sync_root_tracker);
84  DCHECK(should_success);
85
86  DCHECK(!folder_creator_);
87  folder_creator_.reset(new FolderCreator(
88      drive_service(), metadata_database(),
89      sync_root_tracker.file_id(), app_id_));
90  folder_creator_->Run(base::Bind(
91      &RegisterAppTask::DidCreateAppRootFolder,
92      weak_ptr_factory_.GetWeakPtr(), callback));
93}
94
95void RegisterAppTask::DidCreateAppRootFolder(
96    const SyncStatusCallback& callback,
97    const std::string& folder_id,
98    SyncStatusCode status) {
99  scoped_ptr<FolderCreator> deleter = folder_creator_.Pass();
100  if (status != SYNC_STATUS_OK) {
101    callback.Run(status);
102    return;
103  }
104
105  Run(callback);
106}
107
108bool RegisterAppTask::FilterCandidates(const TrackerSet& trackers,
109                                       FileTracker* candidate) {
110  DCHECK(candidate);
111  if (trackers.has_active()) {
112    *candidate = *trackers.active_tracker();
113    return true;
114  }
115
116  FileTracker* oldest_tracker = NULL;
117  for (TrackerSet::const_iterator itr = trackers.begin();
118       itr != trackers.end(); ++itr) {
119    FileTracker* tracker = *itr;
120    FileMetadata file;
121    DCHECK(!tracker->active());
122    DCHECK(tracker->has_synced_details());
123
124    if (!metadata_database()->FindFileByFileID(tracker->file_id(), &file)) {
125      NOTREACHED();
126      // The parent folder is sync-root, whose contents are fetched in
127      // initialization sequence.
128      // So at this point, direct children of sync-root should have
129      // FileMetadata.
130      continue;
131    }
132
133    if (file.details().file_kind() != FILE_KIND_FOLDER)
134      continue;
135
136    if (file.details().missing())
137      continue;
138
139    if (oldest_tracker && CompareOnCTime(*oldest_tracker, *tracker))
140      continue;
141
142    oldest_tracker = tracker;
143  }
144
145  if (!oldest_tracker)
146    return false;
147
148  *candidate = *oldest_tracker;
149  return true;
150}
151
152void RegisterAppTask::RegisterAppIntoDatabase(
153    const FileTracker& tracker,
154    const SyncStatusCallback& callback) {
155  metadata_database()->RegisterApp(
156      app_id_, tracker.file_id(), callback);
157}
158
159MetadataDatabase* RegisterAppTask::metadata_database() {
160  return sync_context_->GetMetadataDatabase();
161}
162
163drive::DriveServiceInterface* RegisterAppTask::drive_service() {
164  return sync_context_->GetDriveService();
165}
166
167}  // namespace drive_backend
168}  // namespace sync_file_system
169