Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Side by Side Diff: chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc

Issue 23949002: [SyncFS] Implement SyncEngineInitializer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer. h" 5 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer. h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "chrome/browser/drive/drive_api_service.h"
11 #include "chrome/browser/drive/drive_api_util.h"
12 #include "chrome/browser/google_apis/drive_api_parser.h"
10 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 13 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
14 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_util. h"
11 15
12 namespace sync_file_system { 16 namespace sync_file_system {
13 namespace drive_backend { 17 namespace drive_backend {
14 18
19 namespace {
20
21 // TODO(tzik): Move them to separate file.
22 const char kSyncRootFolderTitle[] = "Chrome Syncable FileSystem";
23
24 ////////////////////////////////////////////////////////////////////////////////
25 // Functions below are for wrapping the access to legacy GData WAPI classes.
26
27 bool IsDeleted(const google_apis::ResourceEntry& entry) {
28 return entry.deleted();
29 }
30
31 bool HasNoParents(const google_apis::ResourceEntry& entry) {
32 return !entry.GetLinkByType(google_apis::Link::LINK_PARENT);
33 }
34
35 bool HasFolderAsParent(const google_apis::ResourceEntry& entry,
36 const std::string& parent_id) {
37 const ScopedVector<google_apis::Link>& links = entry.links();
38 for (ScopedVector<google_apis::Link>::const_iterator itr = links.begin();
39 itr != links.end(); ++itr) {
40 const google_apis::Link& link = **itr;
41 if (link.type() != google_apis::Link::LINK_PARENT)
42 continue;
43 if (drive::util::ExtractResourceIdFromUrl(link.href()) == parent_id)
44 return true;
45 }
46 return false;
47 }
48
49 bool LessOnCreationTime(const google_apis::ResourceEntry& left,
50 const google_apis::ResourceEntry& right) {
51 return left.published_time() < right.published_time();
52 }
53
54 // Posts a request to continue listing. Returns false if the list doesn't need
55 // listing anymore.
56 bool GetRemainingFileList(
57 google_apis::CancelCallback* cancel_callback,
58 drive::DriveServiceInterface* api_service,
59 const google_apis::ResourceList& resource_list,
60 const google_apis::GetResourceListCallback& callback) {
61 GURL next_url;
62 if (!resource_list.GetNextFeedURL(&next_url))
63 return false;
64
65 *cancel_callback = api_service->GetRemainingFileList(next_url, callback);
66 return true;
67 }
68
69 std::string GetID(const google_apis::ResourceEntry& entry) {
70 return entry.resource_id();
71 }
72
73 ScopedVector<google_apis::FileResource> ConvertResourceEntriesToFileResources(
74 const ScopedVector<google_apis::ResourceEntry>& entries) {
75 ScopedVector<google_apis::FileResource> resources;
76 for (ScopedVector<google_apis::ResourceEntry>::const_iterator itr =
77 entries.begin();
78 itr != entries.end();
79 ++itr) {
80 resources.push_back(
81 drive::util::ConvertResourceEntryToFileResource(
82 **itr).release());
83 }
84 return resources.Pass();
85 }
86
87 // Functions above are for wrapping the access to legacy GData WAPI classes.
88 ////////////////////////////////////////////////////////////////////////////////
89
90 } // namespace
91
15 SyncEngineInitializer::SyncEngineInitializer( 92 SyncEngineInitializer::SyncEngineInitializer(
16 base::SequencedTaskRunner* task_runner, 93 base::SequencedTaskRunner* task_runner,
17 drive::DriveAPIService* drive_api, 94 drive::DriveServiceInterface* drive_service,
18 const base::FilePath& database_path) 95 const base::FilePath& database_path)
19 : task_runner_(task_runner), 96 : task_runner_(task_runner),
20 drive_api_(drive_api), 97 drive_service_(drive_service),
21 database_path_(database_path), 98 database_path_(database_path),
99 largest_change_id_(0),
22 weak_ptr_factory_(this) { 100 weak_ptr_factory_(this) {
101 DCHECK(task_runner);
102 DCHECK(drive_service_);
23 } 103 }
24 104
25 SyncEngineInitializer::~SyncEngineInitializer() { 105 SyncEngineInitializer::~SyncEngineInitializer() {
26 NOTIMPLEMENTED(); 106 if (!cancel_callback_.is_null())
107 cancel_callback_.Run();
27 } 108 }
28 109
29 void SyncEngineInitializer::Run(const SyncStatusCallback& callback) { 110 void SyncEngineInitializer::Run(const SyncStatusCallback& callback) {
30 MetadataDatabase::Create( 111 MetadataDatabase::Create(
31 task_runner_.get(), database_path_, 112 task_runner_.get(), database_path_,
32 base::Bind(&SyncEngineInitializer::DidCreateMetadataDatabase, 113 base::Bind(&SyncEngineInitializer::DidCreateMetadataDatabase,
33 weak_ptr_factory_.GetWeakPtr(), callback)); 114 weak_ptr_factory_.GetWeakPtr(), callback));
34 } 115 }
35 116
117 scoped_ptr<MetadataDatabase> SyncEngineInitializer::PassMetadataDatabase() {
118 return metadata_database_.Pass();
119 }
120
36 void SyncEngineInitializer::DidCreateMetadataDatabase( 121 void SyncEngineInitializer::DidCreateMetadataDatabase(
37 const SyncStatusCallback& callback, 122 const SyncStatusCallback& callback,
38 SyncStatusCode status, 123 SyncStatusCode status,
39 scoped_ptr<MetadataDatabase> instance) { 124 scoped_ptr<MetadataDatabase> instance) {
40 if (status != SYNC_STATUS_OK) { 125 if (status != SYNC_STATUS_OK) {
41 callback.Run(status); 126 callback.Run(status);
42 return; 127 return;
43 } 128 }
44 129
130 DCHECK(instance);
45 metadata_database_ = instance.Pass(); 131 metadata_database_ = instance.Pass();
46 132 if (metadata_database_->HasSyncRoot()) {
47 // TODO(tzik): Set up sync root and populate database with initial folder 133 callback.Run(SYNC_STATUS_OK);
48 // tree. 134 return;
49 135 }
50 NOTIMPLEMENTED(); 136
51 callback.Run(SYNC_STATUS_FAILED); 137 GetAboutResource(callback);
138 }
139
140 void SyncEngineInitializer::GetAboutResource(
141 const SyncStatusCallback& callback) {
142 drive_service_->GetAboutResource(
143 base::Bind(&SyncEngineInitializer::DidGetAboutResource,
144 weak_ptr_factory_.GetWeakPtr(), callback));
145 }
146
147 void SyncEngineInitializer::DidGetAboutResource(
148 const SyncStatusCallback& callback,
149 google_apis::GDataErrorCode error,
150 scoped_ptr<google_apis::AboutResource> about_resource) {
151 cancel_callback_.Reset();
152 if (error != google_apis::HTTP_SUCCESS) {
153 callback.Run(GDataErrorCodeToSyncStatusCode(error));
154 return;
155 }
156
157 DCHECK(about_resource);
158 root_folder_id_ = about_resource->root_folder_id();
159 largest_change_id_ = about_resource->largest_change_id();
160
161 DCHECK(!root_folder_id_.empty());
162 FindSyncRoot(callback);
163 }
164
165 void SyncEngineInitializer::FindSyncRoot(const SyncStatusCallback& callback) {
166 cancel_callback_ = drive_service_->SearchByTitle(
167 kSyncRootFolderTitle,
168 std::string(), // parent_folder_id
169 base::Bind(&SyncEngineInitializer::DidFindSyncRoot,
170 weak_ptr_factory_.GetWeakPtr(),
171 callback));
172 }
173
174 void SyncEngineInitializer::DidFindSyncRoot(
175 const SyncStatusCallback& callback,
176 google_apis::GDataErrorCode error,
177 scoped_ptr<google_apis::ResourceList> resource_list) {
178 cancel_callback_.Reset();
179 if (error != google_apis::HTTP_SUCCESS) {
180 callback.Run(GDataErrorCodeToSyncStatusCode(error));
181 return;
182 }
183
184 ScopedVector<google_apis::ResourceEntry>* entries =
185 resource_list->mutable_entries();
186 for (ScopedVector<google_apis::ResourceEntry>::iterator itr =
187 entries->begin();
188 itr != entries->end(); ++itr) {
189 google_apis::ResourceEntry* entry = *itr;
190
191 // Ignore deleted folder.
192 if (IsDeleted(*entry))
193 continue;
194
195 // Pick an orphaned folder or a direct child of the root folder and
196 // ignore others.
197 DCHECK(!root_folder_id_.empty());
198 if (!HasNoParents(*entry) && !HasFolderAsParent(*entry, root_folder_id_))
199 continue;
200
201 if (!sync_root_folder_ || LessOnCreationTime(*entry, *sync_root_folder_)) {
202 sync_root_folder_.reset(entry);
203 *itr = NULL;
204 }
205 }
206
207 // If there are more results, retrieve them.
208 if (GetRemainingFileList(
209 &cancel_callback_,
210 drive_service_, *resource_list,
211 base::Bind(&SyncEngineInitializer::DidFindSyncRoot,
212 weak_ptr_factory_.GetWeakPtr(),
213 callback)))
214 return;
215
216 if (!sync_root_folder_) {
217 CreateSyncRoot(callback);
218 return;
219 }
220
221 if (!HasNoParents(*sync_root_folder_)) {
222 DetachSyncRoot(callback);
223 return;
224 }
225
226 ListAppRootFolders(callback);
227 }
228
229 void SyncEngineInitializer::CreateSyncRoot(const SyncStatusCallback& callback) {
230 DCHECK(!sync_root_folder_);
231 cancel_callback_ = drive_service_->AddNewDirectory(
232 root_folder_id_, kSyncRootFolderTitle,
233 base::Bind(&SyncEngineInitializer::DidCreateSyncRoot,
234 weak_ptr_factory_.GetWeakPtr(),
235 callback));
236 }
237
238 void SyncEngineInitializer::DidCreateSyncRoot(
239 const SyncStatusCallback& callback,
240 google_apis::GDataErrorCode error,
241 scoped_ptr<google_apis::ResourceEntry> entry) {
242 DCHECK(!sync_root_folder_);
243 cancel_callback_.Reset();
244 if (error != google_apis::HTTP_SUCCESS &&
245 error != google_apis::HTTP_CREATED) {
246 callback.Run(GDataErrorCodeToSyncStatusCode(error));
247 return;
248 }
249
250 FindSyncRoot(callback);
251 }
252
253 void SyncEngineInitializer::DetachSyncRoot(const SyncStatusCallback& callback) {
254 DCHECK(sync_root_folder_);
255 cancel_callback_ = drive_service_->RemoveResourceFromDirectory(
256 root_folder_id_, GetID(*sync_root_folder_),
257 base::Bind(&SyncEngineInitializer::DidDetachSyncRoot,
258 weak_ptr_factory_.GetWeakPtr(),
259 callback));
260 }
261
262 void SyncEngineInitializer::DidDetachSyncRoot(
263 const SyncStatusCallback& callback,
264 google_apis::GDataErrorCode error) {
265 cancel_callback_.Reset();
266 if (error != google_apis::HTTP_SUCCESS) {
267 callback.Run(GDataErrorCodeToSyncStatusCode(error));
268 return;
269 }
270 ListAppRootFolders(callback);
271 }
272
273 void SyncEngineInitializer::ListAppRootFolders(
274 const SyncStatusCallback& callback) {
275 DCHECK(sync_root_folder_);
276 cancel_callback_ = drive_service_->GetResourceListInDirectory(
277 GetID(*sync_root_folder_),
278 base::Bind(&SyncEngineInitializer::DidListAppRootFolders,
279 weak_ptr_factory_.GetWeakPtr(),
280 callback));
281 }
282
283 void SyncEngineInitializer::DidListAppRootFolders(
284 const SyncStatusCallback& callback,
285 google_apis::GDataErrorCode error,
286 scoped_ptr<google_apis::ResourceList> resource_list) {
287 cancel_callback_.Reset();
288 if (error != google_apis::HTTP_SUCCESS) {
289 callback.Run(GDataErrorCodeToSyncStatusCode(error));
290 return;
291 }
292
293 ScopedVector<google_apis::ResourceEntry>* new_entries =
294 resource_list->mutable_entries();
295 app_root_folders_.insert(app_root_folders_.end(),
296 new_entries->begin(), new_entries->end());
297 new_entries->weak_clear();
298
299 if (GetRemainingFileList(
300 &cancel_callback_,
301 drive_service_,
302 *resource_list,
303 base::Bind(&SyncEngineInitializer::DidListAppRootFolders,
304 weak_ptr_factory_.GetWeakPtr(), callback)))
305 return;
306
307 PopulateDatabase(callback);
308 }
309
310 void SyncEngineInitializer::PopulateDatabase(
311 const SyncStatusCallback& callback) {
312 DCHECK(sync_root_folder_);
313 metadata_database_->PopulateInitialData(
314 largest_change_id_,
315 *drive::util::ConvertResourceEntryToFileResource(
316 *sync_root_folder_),
317 ConvertResourceEntriesToFileResources(app_root_folders_),
318 base::Bind(&SyncEngineInitializer::DidPopulateDatabase,
319 weak_ptr_factory_.GetWeakPtr(),
320 callback));
321 }
322
323 void SyncEngineInitializer::DidPopulateDatabase(
324 const SyncStatusCallback& callback,
325 SyncStatusCode status) {
326 if (status != SYNC_STATUS_OK) {
327 callback.Run(status);
328 return;
329 }
330
331 callback.Run(SYNC_STATUS_OK);
52 } 332 }
53 333
54 } // namespace drive_backend 334 } // namespace drive_backend
55 } // namespace sync_file_system 335 } // namespace sync_file_system
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698