| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/sync/engine_impl/loopback_server/loopback_server.h" | 5 #include "components/sync/engine_impl/loopback_server/loopback_server.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 const ModelTypeToVersionMap request_version_map_; | 127 const ModelTypeToVersionMap request_version_map_; |
| 128 | 128 |
| 129 // The largest versions seen between client and server, ultimately used to | 129 // The largest versions seen between client and server, ultimately used to |
| 130 // send progress markers back to the client. | 130 // send progress markers back to the client. |
| 131 ModelTypeToVersionMap response_version_map_; | 131 ModelTypeToVersionMap response_version_map_; |
| 132 }; | 132 }; |
| 133 | 133 |
| 134 } // namespace | 134 } // namespace |
| 135 | 135 |
| 136 LoopbackServer::LoopbackServer(const base::FilePath& persistent_file) | 136 LoopbackServer::LoopbackServer(const base::FilePath& persistent_file) |
| 137 : version_(0), | 137 : version_(0), store_birthday_(0), persistent_file_(persistent_file) { |
| 138 store_birthday_(0), | |
| 139 persistent_file_(persistent_file), | |
| 140 observer_for_tests_(NULL) { | |
| 141 Init(); | 138 Init(); |
| 142 } | 139 } |
| 143 | 140 |
| 144 LoopbackServer::~LoopbackServer() {} | 141 LoopbackServer::~LoopbackServer() {} |
| 145 | 142 |
| 146 void LoopbackServer::Init() { | 143 void LoopbackServer::Init() { |
| 147 if (LoadStateFromFile(persistent_file_)) | 144 if (LoadStateFromFile(persistent_file_)) |
| 148 return; | 145 return; |
| 149 | 146 |
| 150 keystore_keys_.push_back(GenerateNewKeystoreKey()); | 147 keystore_keys_.push_back(GenerateNewKeystoreKey()); |
| 151 | 148 |
| 152 const bool create_result = CreateDefaultPermanentItems(); | 149 const bool create_result = CreateDefaultPermanentItems(); |
| 153 DCHECK(create_result) << "Permanent items were not created successfully."; | 150 DCHECK(create_result) << "Permanent items were not created successfully."; |
| 154 } | 151 } |
| 155 | 152 |
| 156 std::string LoopbackServer::GenerateNewKeystoreKey() const { | 153 std::string LoopbackServer::GenerateNewKeystoreKey() const { |
| 157 // TODO(pastarmovj): Check if true random bytes is ok or alpha-nums is needed? | 154 // TODO(pastarmovj): Check if true random bytes is ok or alpha-nums is needed? |
| 158 return base::RandBytesAsString(kKeystoreKeyLenght); | 155 return base::RandBytesAsString(kKeystoreKeyLenght); |
| 159 } | 156 } |
| 160 | 157 |
| 161 bool LoopbackServer::CreatePermanentBookmarkFolder( | 158 bool LoopbackServer::CreatePermanentBookmarkFolder( |
| 162 const std::string& server_tag, | 159 const std::string& server_tag, |
| 163 const std::string& name) { | 160 const std::string& name) { |
| 164 DCHECK(thread_checker_.CalledOnValidThread()); | 161 DCHECK(thread_checker_.CalledOnValidThread()); |
| 165 std::unique_ptr<LoopbackServerEntity> entity = | 162 std::unique_ptr<LoopbackServerEntity> entity = |
| 166 PersistentPermanentEntity::CreateNew( | 163 PersistentPermanentEntity::Create(syncer::BOOKMARKS, server_tag, name, |
| 167 syncer::BOOKMARKS, server_tag, name, | 164 ModelTypeToRootTag(syncer::BOOKMARKS)); |
| 168 ModelTypeToRootTag(syncer::BOOKMARKS)); | |
| 169 if (!entity) | 165 if (!entity) |
| 170 return false; | 166 return false; |
| 171 | 167 |
| 172 SaveEntity(std::move(entity)); | 168 SaveEntity(std::move(entity)); |
| 173 return true; | 169 return true; |
| 174 } | 170 } |
| 175 | 171 |
| 176 bool LoopbackServer::CreateDefaultPermanentItems() { | 172 bool LoopbackServer::CreateDefaultPermanentItems() { |
| 177 // Permanent folders are always required for Bookmarks (hierarchical | 173 // Permanent folders are always required for Bookmarks (hierarchical |
| 178 // structure) and Nigori (data stored in permanent root folder). | 174 // structure) and Nigori (data stored in permanent root folder). |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 const sync_pb::SyncEntity& client_entity, | 317 const sync_pb::SyncEntity& client_entity, |
| 322 sync_pb::CommitResponse_EntryResponse* entry_response, | 318 sync_pb::CommitResponse_EntryResponse* entry_response, |
| 323 const string& client_guid, | 319 const string& client_guid, |
| 324 const string& parent_id) { | 320 const string& parent_id) { |
| 325 if (client_entity.version() == 0 && client_entity.deleted()) { | 321 if (client_entity.version() == 0 && client_entity.deleted()) { |
| 326 return string(); | 322 return string(); |
| 327 } | 323 } |
| 328 | 324 |
| 329 std::unique_ptr<LoopbackServerEntity> entity; | 325 std::unique_ptr<LoopbackServerEntity> entity; |
| 330 if (client_entity.deleted()) { | 326 if (client_entity.deleted()) { |
| 331 entity = PersistentTombstoneEntity::CreateFromEntity(client_entity); | 327 entity = PersistentTombstoneEntity::Create(client_entity); |
| 332 DeleteChildren(client_entity.id_string()); | 328 DeleteChildren(client_entity.id_string()); |
| 333 } else if (GetModelType(client_entity) == syncer::NIGORI) { | 329 } else if (GetModelType(client_entity) == syncer::NIGORI) { |
| 334 // NIGORI is the only permanent item type that should be updated by the | 330 // NIGORI is the only permanent item type that should be updated by the |
| 335 // client. | 331 // client. |
| 336 EntityMap::const_iterator iter = entities_.find(client_entity.id_string()); | 332 EntityMap::const_iterator iter = entities_.find(client_entity.id_string()); |
| 337 CHECK(iter != entities_.end()); | 333 CHECK(iter != entities_.end()); |
| 338 entity = PersistentPermanentEntity::CreateUpdatedNigoriEntity( | 334 entity = PersistentPermanentEntity::CreateUpdatedNigoriEntity( |
| 339 client_entity, *iter->second); | 335 client_entity, *iter->second); |
| 340 } else if (client_entity.has_client_defined_unique_tag()) { | 336 } else if (client_entity.has_client_defined_unique_tag()) { |
| 341 entity = PersistentUniqueClientEntity::CreateFromEntity(client_entity); | 337 entity = PersistentUniqueClientEntity::Create(client_entity); |
| 342 } else { | 338 } else { |
| 343 // TODO(pvalenzuela): Validate entity's parent ID. | 339 // TODO(pvalenzuela): Validate entity's parent ID. |
| 344 EntityMap::const_iterator iter = entities_.find(client_entity.id_string()); | 340 EntityMap::const_iterator iter = entities_.find(client_entity.id_string()); |
| 345 if (iter != entities_.end()) { | 341 if (iter != entities_.end()) { |
| 346 entity = PersistentBookmarkEntity::CreateUpdatedVersion( | 342 entity = PersistentBookmarkEntity::CreateUpdatedVersion( |
| 347 client_entity, *iter->second, parent_id); | 343 client_entity, *iter->second, parent_id); |
| 348 } else { | 344 } else { |
| 349 entity = PersistentBookmarkEntity::CreateNew(client_entity, parent_id, | 345 entity = PersistentBookmarkEntity::CreateNew(client_entity, parent_id, |
| 350 client_guid); | 346 client_guid); |
| 351 } | 347 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 // Find all the children of id. | 399 // Find all the children of id. |
| 404 for (auto& entity : entities_) { | 400 for (auto& entity : entities_) { |
| 405 if (IsChild(entity.first, id)) { | 401 if (IsChild(entity.first, id)) { |
| 406 sync_pb::SyncEntity proto; | 402 sync_pb::SyncEntity proto; |
| 407 entity.second->SerializeAsProto(&proto); | 403 entity.second->SerializeAsProto(&proto); |
| 408 tombstones.emplace_back(proto); | 404 tombstones.emplace_back(proto); |
| 409 } | 405 } |
| 410 } | 406 } |
| 411 | 407 |
| 412 for (auto& tombstone : tombstones) { | 408 for (auto& tombstone : tombstones) { |
| 413 SaveEntity(PersistentTombstoneEntity::CreateFromEntity(tombstone)); | 409 SaveEntity(PersistentTombstoneEntity::Create(tombstone)); |
| 414 } | 410 } |
| 415 } | 411 } |
| 416 | 412 |
| 417 bool LoopbackServer::HandleCommitRequest( | 413 bool LoopbackServer::HandleCommitRequest( |
| 418 const sync_pb::CommitMessage& commit, | 414 const sync_pb::CommitMessage& commit, |
| 419 const std::string& invalidator_client_id, | 415 const std::string& invalidator_client_id, |
| 420 sync_pb::CommitResponse* response) { | 416 sync_pb::CommitResponse* response) { |
| 421 std::map<string, string> client_to_server_ids; | 417 std::map<string, string> client_to_server_ids; |
| 422 string guid = commit.cache_guid(); | 418 string guid = commit.cache_guid(); |
| 423 ModelTypeSet committed_model_types; | 419 ModelTypeSet committed_model_types; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 443 // Record the ID if it was renamed. | 439 // Record the ID if it was renamed. |
| 444 if (entity_id != client_entity.id_string()) { | 440 if (entity_id != client_entity.id_string()) { |
| 445 client_to_server_ids[client_entity.id_string()] = entity_id; | 441 client_to_server_ids[client_entity.id_string()] = entity_id; |
| 446 } | 442 } |
| 447 | 443 |
| 448 EntityMap::const_iterator iter = entities_.find(entity_id); | 444 EntityMap::const_iterator iter = entities_.find(entity_id); |
| 449 CHECK(iter != entities_.end()); | 445 CHECK(iter != entities_.end()); |
| 450 committed_model_types.Put(iter->second->GetModelType()); | 446 committed_model_types.Put(iter->second->GetModelType()); |
| 451 } | 447 } |
| 452 | 448 |
| 453 if (observer_for_tests_) | |
| 454 observer_for_tests_->OnCommit(invalidator_client_id, committed_model_types); | |
| 455 | |
| 456 return true; | 449 return true; |
| 457 } | 450 } |
| 458 | 451 |
| 459 void LoopbackServer::ClearServerData() { | 452 void LoopbackServer::ClearServerData() { |
| 460 DCHECK(thread_checker_.CalledOnValidThread()); | 453 DCHECK(thread_checker_.CalledOnValidThread()); |
| 461 entities_.clear(); | 454 entities_.clear(); |
| 462 keystore_keys_.clear(); | 455 keystore_keys_.clear(); |
| 463 ++store_birthday_; | 456 ++store_birthday_; |
| 464 base::DeleteFile(persistent_file_, false); | |
| 465 Init(); | 457 Init(); |
| 466 } | 458 } |
| 467 | 459 |
| 468 std::string LoopbackServer::GetStoreBirthday() const { | 460 std::string LoopbackServer::GetStoreBirthday() const { |
| 469 DCHECK(thread_checker_.CalledOnValidThread()); | 461 DCHECK(thread_checker_.CalledOnValidThread()); |
| 470 return base::Int64ToString(store_birthday_); | 462 return base::Int64ToString(store_birthday_); |
| 471 } | 463 } |
| 472 | 464 |
| 473 std::vector<sync_pb::SyncEntity> LoopbackServer::GetSyncEntitiesByModelType( | |
| 474 ModelType model_type) { | |
| 475 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 476 std::vector<sync_pb::SyncEntity> sync_entities; | |
| 477 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); | |
| 478 ++it) { | |
| 479 const LoopbackServerEntity& entity = *it->second; | |
| 480 if (!(entity.IsDeleted() || entity.IsPermanent()) && | |
| 481 entity.GetModelType() == model_type) { | |
| 482 sync_pb::SyncEntity sync_entity; | |
| 483 entity.SerializeAsProto(&sync_entity); | |
| 484 sync_entities.push_back(sync_entity); | |
| 485 } | |
| 486 } | |
| 487 return sync_entities; | |
| 488 } | |
| 489 | |
| 490 std::unique_ptr<base::DictionaryValue> | |
| 491 LoopbackServer::GetEntitiesAsDictionaryValue() { | |
| 492 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 493 std::unique_ptr<base::DictionaryValue> dictionary( | |
| 494 new base::DictionaryValue()); | |
| 495 | |
| 496 // Initialize an empty ListValue for all ModelTypes. | |
| 497 ModelTypeSet all_types = ModelTypeSet::All(); | |
| 498 for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) { | |
| 499 dictionary->Set(ModelTypeToString(it.Get()), | |
| 500 base::MakeUnique<base::ListValue>()); | |
| 501 } | |
| 502 | |
| 503 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); | |
| 504 ++it) { | |
| 505 const LoopbackServerEntity& entity = *it->second; | |
| 506 if (entity.IsDeleted() || entity.IsPermanent()) { | |
| 507 // Tombstones are ignored as they don't represent current data. Folders | |
| 508 // are also ignored as current verification infrastructure does not | |
| 509 // consider them. | |
| 510 continue; | |
| 511 } | |
| 512 base::ListValue* list_value; | |
| 513 if (!dictionary->GetList(ModelTypeToString(entity.GetModelType()), | |
| 514 &list_value)) { | |
| 515 return std::unique_ptr<base::DictionaryValue>(); | |
| 516 } | |
| 517 // TODO(pvalenzuela): Store more data for each entity so additional | |
| 518 // verification can be performed. One example of additional verification | |
| 519 // is checking the correctness of the bookmark hierarchy. | |
| 520 list_value->AppendString(entity.GetName()); | |
| 521 } | |
| 522 | |
| 523 return dictionary; | |
| 524 } | |
| 525 | |
| 526 bool LoopbackServer::ModifyEntitySpecifics( | |
| 527 const std::string& id, | |
| 528 const sync_pb::EntitySpecifics& updated_specifics) { | |
| 529 EntityMap::const_iterator iter = entities_.find(id); | |
| 530 if (iter == entities_.end() || | |
| 531 iter->second->GetModelType() != | |
| 532 GetModelTypeFromSpecifics(updated_specifics)) { | |
| 533 return false; | |
| 534 } | |
| 535 | |
| 536 LoopbackServerEntity* entity = iter->second.get(); | |
| 537 entity->SetSpecifics(updated_specifics); | |
| 538 UpdateEntityVersion(entity); | |
| 539 return true; | |
| 540 } | |
| 541 | |
| 542 bool LoopbackServer::ModifyBookmarkEntity( | |
| 543 const std::string& id, | |
| 544 const std::string& parent_id, | |
| 545 const sync_pb::EntitySpecifics& updated_specifics) { | |
| 546 EntityMap::const_iterator iter = entities_.find(id); | |
| 547 if (iter == entities_.end() || | |
| 548 iter->second->GetModelType() != syncer::BOOKMARKS || | |
| 549 GetModelTypeFromSpecifics(updated_specifics) != syncer::BOOKMARKS) { | |
| 550 return false; | |
| 551 } | |
| 552 | |
| 553 PersistentBookmarkEntity* entity = | |
| 554 static_cast<PersistentBookmarkEntity*>(iter->second.get()); | |
| 555 | |
| 556 entity->SetParentId(parent_id); | |
| 557 entity->SetSpecifics(updated_specifics); | |
| 558 if (updated_specifics.has_bookmark()) { | |
| 559 entity->SetName(updated_specifics.bookmark().title()); | |
| 560 } | |
| 561 UpdateEntityVersion(entity); | |
| 562 return true; | |
| 563 } | |
| 564 | |
| 565 void LoopbackServer::SerializeState(sync_pb::LoopbackServerProto* proto) const { | 465 void LoopbackServer::SerializeState(sync_pb::LoopbackServerProto* proto) const { |
| 566 DCHECK(thread_checker_.CalledOnValidThread()); | 466 DCHECK(thread_checker_.CalledOnValidThread()); |
| 567 | 467 |
| 568 proto->set_version(kCurrentLoopbackServerProtoVersion); | 468 proto->set_version(kCurrentLoopbackServerProtoVersion); |
| 569 proto->set_store_birthday(store_birthday_); | 469 proto->set_store_birthday(store_birthday_); |
| 570 proto->set_last_version_assigned(version_); | 470 proto->set_last_version_assigned(version_); |
| 571 for (const auto& key : keystore_keys_) | 471 for (const auto& key : keystore_keys_) |
| 572 proto->add_keystore_keys(key); | 472 proto->add_keystore_keys(key); |
| 573 for (const auto& entity : entities_) { | 473 for (const auto& entity : entities_) { |
| 574 auto* new_entity = proto->mutable_entities()->Add(); | 474 auto* new_entity = proto->mutable_entities()->Add(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 // write. | 528 // write. |
| 629 LOG(ERROR) << "Loopback sync can not read the persistent state file."; | 529 LOG(ERROR) << "Loopback sync can not read the persistent state file."; |
| 630 return false; | 530 return false; |
| 631 } | 531 } |
| 632 } | 532 } |
| 633 LOG(WARNING) << "Loopback sync persistent state file does not exist."; | 533 LOG(WARNING) << "Loopback sync persistent state file does not exist."; |
| 634 return false; | 534 return false; |
| 635 } | 535 } |
| 636 | 536 |
| 637 } // namespace syncer | 537 } // namespace syncer |
| OLD | NEW |