Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 |
| OLD | NEW |