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

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: +comment 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"
13 #include "chrome/browser/sync_file_system/drive_backend/drive_file_sync_util.h"
10 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 14 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.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 // These functions touches GData WAPI classes directly.
kinuko 2013/09/09 12:35:50 touches -> touch GData WAPI classes -> google_apis
tzik 2013/09/10 06:00:42 Done. I meant the classes in gdata_wapi_parser.h.
kinuko 2013/09/10 06:43:23 I see, then maybe you can just write like that? "T
tzik 2013/09/10 08:45:44 Done.
25 bool IsDeleted(const google_apis::ResourceEntry& entry) {
26 return entry.deleted();
27 }
28
29 bool HasNoParents(const google_apis::ResourceEntry& entry) {
30 return !entry.GetLinkByType(google_apis::Link::LINK_PARENT);
31 }
32
33 bool HasFolderAsParent(const google_apis::ResourceEntry& entry,
34 const std::string& parent_id) {
35 const ScopedVector<google_apis::Link>& links = entry.links();
36 for (ScopedVector<google_apis::Link>::const_iterator itr = links.begin();
37 itr != links.end(); ++itr) {
38 const google_apis::Link& link = **itr;
39 if (link.type() != google_apis::Link::LINK_PARENT)
40 continue;
41 if (drive::util::ExtractResourceIdFromUrl(link.href()) == parent_id)
42 return true;
43 }
44 return false;
45 }
46
47 bool LessOnCreationTime(const google_apis::ResourceEntry& left,
48 const google_apis::ResourceEntry& right) {
49 return left.published_time() < right.published_time();
50 }
51
52 // Posts a request to continue listing. Returns false if the list don't need
kinuko 2013/09/09 12:35:50 nit: don't -> doesn't
tzik 2013/09/10 06:00:42 Done.
53 // listing anymore.
54 bool GetRemainingFileList(
55 google_apis::CancelCallback* cancel_callback,
56 drive::DriveServiceInterface* api_service,
57 const google_apis::ResourceList& resource_list,
58 const google_apis::GetResourceListCallback& callback) {
59 GURL next_url;
60 if (!resource_list.GetNextFeedURL(&next_url))
61 return false;
62
63 *cancel_callback = api_service->GetRemainingFileList(next_url, callback);
64 return true;
65 }
66
67 std::string GetID(const google_apis::ResourceEntry& entry) {
68 return entry.resource_id();
69 }
70
71 ScopedVector<google_apis::FileResource> ConvertResourceEntriesToFileResources(
72 const ScopedVector<google_apis::ResourceEntry>& entries) {
73 ScopedVector<google_apis::FileResource> resources;
74 for (ScopedVector<google_apis::ResourceEntry>::const_iterator itr =
75 entries.begin();
76 itr != entries.end();
77 ++itr) {
78 resources.push_back(
79 drive::util::ConvertResourceEntryToFileResource(
80 **itr).release());
81 }
82 return resources.Pass();
83 }
84
85 } // namespace
86
15 SyncEngineInitializer::SyncEngineInitializer( 87 SyncEngineInitializer::SyncEngineInitializer(
16 base::SequencedTaskRunner* task_runner, 88 base::SequencedTaskRunner* task_runner,
17 drive::DriveAPIService* drive_api, 89 drive::DriveServiceInterface* drive_api,
18 const base::FilePath& database_path) 90 const base::FilePath& database_path)
19 : task_runner_(task_runner), 91 : task_runner_(task_runner),
20 drive_api_(drive_api), 92 drive_api_(drive_api),
21 database_path_(database_path), 93 database_path_(database_path),
94 largest_change_id_(0),
22 weak_ptr_factory_(this) { 95 weak_ptr_factory_(this) {
96 DCHECK(task_runner);
97 DCHECK(drive_api_);
23 } 98 }
24 99
25 SyncEngineInitializer::~SyncEngineInitializer() { 100 SyncEngineInitializer::~SyncEngineInitializer() {
26 NOTIMPLEMENTED(); 101 if (!cancel_callback_.is_null())
102 cancel_callback_.Run();
27 } 103 }
28 104
29 void SyncEngineInitializer::Run(const SyncStatusCallback& callback) { 105 void SyncEngineInitializer::Run(const SyncStatusCallback& callback) {
30 MetadataDatabase::Create( 106 MetadataDatabase::Create(
31 task_runner_.get(), database_path_, 107 task_runner_.get(), database_path_,
32 base::Bind(&SyncEngineInitializer::DidCreateMetadataDatabase, 108 base::Bind(&SyncEngineInitializer::DidCreateMetadataDatabase,
33 weak_ptr_factory_.GetWeakPtr(), callback)); 109 weak_ptr_factory_.GetWeakPtr(), callback));
34 } 110 }
35 111
112 scoped_ptr<MetadataDatabase> SyncEngineInitializer::PassMetadataDatabase() {
113 return metadata_database_.Pass();
114 }
115
36 void SyncEngineInitializer::DidCreateMetadataDatabase( 116 void SyncEngineInitializer::DidCreateMetadataDatabase(
37 const SyncStatusCallback& callback, 117 const SyncStatusCallback& callback,
38 SyncStatusCode status, 118 SyncStatusCode status,
39 scoped_ptr<MetadataDatabase> instance) { 119 scoped_ptr<MetadataDatabase> instance) {
40 if (status != SYNC_STATUS_OK) { 120 if (status != SYNC_STATUS_OK) {
41 callback.Run(status); 121 callback.Run(status);
42 return; 122 return;
43 } 123 }
44 124
45 metadata_database_ = instance.Pass(); 125 metadata_database_ = instance.Pass();
46 126 if (metadata_database_->HasSyncRoot()) {
47 // TODO(tzik): Set up sync root and populate database with initial folder 127 callback.Run(SYNC_STATUS_OK);
48 // tree. 128 return;
49 129 }
50 NOTIMPLEMENTED(); 130
51 callback.Run(SYNC_STATUS_FAILED); 131 GetAboutResource(callback);
132 }
133
134 void SyncEngineInitializer::GetAboutResource(
135 const SyncStatusCallback& callback) {
136 drive_api_->GetAboutResource(
137 base::Bind(&SyncEngineInitializer::DidGetAboutResource,
138 weak_ptr_factory_.GetWeakPtr(), callback));
139 }
140
141 void SyncEngineInitializer::DidGetAboutResource(
142 const SyncStatusCallback& callback,
143 google_apis::GDataErrorCode error,
144 scoped_ptr<google_apis::AboutResource> about_resource) {
145 cancel_callback_.Reset();
146 if (error != google_apis::HTTP_SUCCESS) {
147 callback.Run(GDataErrorCodeToSyncStatusCode(error));
148 return;
149 }
150
151 DCHECK(about_resource);
152 root_folder_id_ = about_resource->root_folder_id();
153 largest_change_id_ = about_resource->largest_change_id();
154
155 DCHECK(!root_folder_id_.empty());
156 FindSyncRoot(callback);
157 }
158
159 void SyncEngineInitializer::FindSyncRoot(const SyncStatusCallback& callback) {
160 cancel_callback_ = drive_api_->SearchByTitle(
161 kSyncRootFolderTitle,
162 std::string(), // parent_folder_id
163 base::Bind(&SyncEngineInitializer::DidFindSyncRoot,
164 weak_ptr_factory_.GetWeakPtr(),
165 callback));
166 }
167
168 void SyncEngineInitializer::DidFindSyncRoot(
169 const SyncStatusCallback& callback,
170 google_apis::GDataErrorCode error,
171 scoped_ptr<google_apis::ResourceList> resource_list) {
172 cancel_callback_.Reset();
173 if (error != google_apis::HTTP_SUCCESS) {
174 callback.Run(GDataErrorCodeToSyncStatusCode(error));
175 return;
176 }
177
178 ScopedVector<google_apis::ResourceEntry>* entries =
179 resource_list->mutable_entries();
180 for (ScopedVector<google_apis::ResourceEntry>::iterator itr =
181 entries->begin();
182 itr != entries->end(); ++itr) {
183 google_apis::ResourceEntry* entry = *itr;
184
185 // Ignore deleted folder.
186 if (IsDeleted(*entry))
187 continue;
188
189 // Pick an orphaned folder or a direct child of the the root folder and
nhiroki 2013/09/09 14:21:57 "the the" -> "the"
tzik 2013/09/10 06:00:42 Done.
190 // ignore others.
191 DCHECK(!root_folder_id_.empty());
192 if (!HasNoParents(*entry) && !HasFolderAsParent(*entry, root_folder_id_))
193 continue;
194
195 if (!sync_root_folder_ || LessOnCreationTime(*entry, *sync_root_folder_)) {
196 sync_root_folder_.reset(entry);
197 *itr = NULL;
198 }
199 }
200
201 // If there are more result, retrieve them.
nhiroki 2013/09/09 14:21:57 "result" -> "results"
tzik 2013/09/10 06:00:42 Done.
202 if (GetRemainingFileList(
203 &cancel_callback_,
204 drive_api_, *resource_list,
205 base::Bind(&SyncEngineInitializer::DidFindSyncRoot,
206 weak_ptr_factory_.GetWeakPtr(),
207 callback)))
208 return;
209
210 if (!sync_root_folder_) {
211 CreateSyncRoot(callback);
212 return;
213 }
214
215 if (!HasNoParents(*sync_root_folder_)) {
216 DetachSyncRoot(callback);
217 return;
218 }
219
220 ListAppRootFolders(callback);
221 }
222
223 void SyncEngineInitializer::CreateSyncRoot(const SyncStatusCallback& callback) {
224 cancel_callback_ = drive_api_->AddNewDirectory(
225 root_folder_id_, kSyncRootFolderTitle,
226 base::Bind(&SyncEngineInitializer::DidCreateSyncRoot,
227 weak_ptr_factory_.GetWeakPtr(),
228 callback));
229 }
230
231 void SyncEngineInitializer::DidCreateSyncRoot(
232 const SyncStatusCallback& callback,
233 google_apis::GDataErrorCode error,
234 scoped_ptr<google_apis::ResourceEntry> entry) {
235 cancel_callback_.Reset();
236 if (error != google_apis::HTTP_SUCCESS &&
237 error != google_apis::HTTP_CREATED) {
238 callback.Run(GDataErrorCodeToSyncStatusCode(error));
239 return;
240 }
241
242 FindSyncRoot(callback);
243 }
244
245 void SyncEngineInitializer::DetachSyncRoot(const SyncStatusCallback& callback) {
nhiroki 2013/09/09 14:21:57 Can we have "DCHECK(sync_root_folder_);" here?
tzik 2013/09/10 06:00:42 Done.
246 cancel_callback_ = drive_api_->RemoveResourceFromDirectory(
247 root_folder_id_, GetID(*sync_root_folder_),
248 base::Bind(&SyncEngineInitializer::DidDetachSyncRoot,
249 weak_ptr_factory_.GetWeakPtr(),
250 callback));
251 }
252
253 void SyncEngineInitializer::DidDetachSyncRoot(
254 const SyncStatusCallback& callback,
255 google_apis::GDataErrorCode error) {
256 cancel_callback_.Reset();
257 if (error != google_apis::HTTP_SUCCESS) {
258 callback.Run(GDataErrorCodeToSyncStatusCode(error));
259 return;
260 }
261 ListAppRootFolders(callback);
262 }
263
264 void SyncEngineInitializer::ListAppRootFolders(
265 const SyncStatusCallback& callback) {
266 DCHECK(sync_root_folder_);
267 cancel_callback_ = drive_api_->GetResourceListInDirectory(
268 GetID(*sync_root_folder_),
269 base::Bind(&SyncEngineInitializer::DidListAppRootFolders,
270 weak_ptr_factory_.GetWeakPtr(),
271 callback));
272 }
273
274 void SyncEngineInitializer::DidListAppRootFolders(
275 const SyncStatusCallback& callback,
276 google_apis::GDataErrorCode error,
277 scoped_ptr<google_apis::ResourceList> resource_list) {
278 cancel_callback_.Reset();
279 if (error != google_apis::HTTP_SUCCESS) {
280 callback.Run(GDataErrorCodeToSyncStatusCode(error));
281 return;
282 }
283
284 ScopedVector<google_apis::ResourceEntry>* new_entries =
285 resource_list->mutable_entries();
286 app_root_folders_.insert(app_root_folders_.end(),
287 new_entries->begin(), new_entries->end());
288 new_entries->weak_clear();
289
290 if (GetRemainingFileList(
291 &cancel_callback_,
292 drive_api_,
293 *resource_list,
294 base::Bind(&SyncEngineInitializer::DidListAppRootFolders,
295 weak_ptr_factory_.GetWeakPtr(), callback)))
296 return;
297
298 PopulateDatabase(callback);
299 }
300
301 void SyncEngineInitializer::PopulateDatabase(
302 const SyncStatusCallback& callback) {
303 metadata_database_->PopulateInitialData(
304 largest_change_id_,
305 *drive::util::ConvertResourceEntryToFileResource(
306 *sync_root_folder_),
307 ConvertResourceEntriesToFileResources(app_root_folders_),
308 base::Bind(&SyncEngineInitializer::DidPopulateDatabase,
309 weak_ptr_factory_.GetWeakPtr(),
310 callback));
311 }
312
313 void SyncEngineInitializer::DidPopulateDatabase(
314 const SyncStatusCallback& callback,
315 SyncStatusCode status) {
316 if (status != SYNC_STATUS_OK) {
317 callback.Run(status);
318 return;
319 }
320
321 Finish(callback);
322 }
323
324 void SyncEngineInitializer::Finish(const SyncStatusCallback& callback) {
325 callback.Run(SYNC_STATUS_OK);
kinuko 2013/09/09 12:35:50 Does this indirection have some meaning?
tzik 2013/09/10 06:00:42 Deleted. This was meaningful only for a deleted c
52 } 326 }
53 327
54 } // namespace drive_backend 328 } // namespace drive_backend
55 } // namespace sync_file_system 329 } // namespace sync_file_system
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698