1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/verify_updates_command.h" 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer_proto_util.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer_types.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer_util.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncproto.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/directory_manager.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/syncable.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync { 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::ScopedDirLookup; 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::SyncName; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::WriteTransaction; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::GET_BY_ID; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::SYNCER; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochVerifyUpdatesCommand::VerifyUpdatesCommand() {} 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochVerifyUpdatesCommand::~VerifyUpdatesCommand() {} 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid VerifyUpdatesCommand::ModelChangingExecuteImpl( 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sessions::SyncSession* session) { 31731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Beginning Update Verification"; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedDirLookup dir(session->context()->directory_manager(), 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch session->context()->account_name()); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dir.good()) { 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Scoped dir lookup failed!"; 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WriteTransaction trans(dir, SYNCER, __FILE__, __LINE__); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sessions::StatusController* status = session->status_controller(); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GetUpdatesResponse& updates = status->updates_response().get_updates(); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int update_count = updates.entries().size(); 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << update_count << " entries to verify"; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < update_count; i++) { 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SyncEntity& update = 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *reinterpret_cast<const SyncEntity *>(&(updates.entries(i))); 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelSafeGroup g = GetGroupForModelType(update.GetModelType(), 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch session->routing_info()); 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (g != status->group_restriction()) 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyUpdateResult result = VerifyUpdate(&trans, update, 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch session->routing_info()); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->mutable_update_progress()->AddVerifyResult(result.value, update); 5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen status->increment_num_updates_downloaded_by(1); 5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (update.deleted()) 5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen status->increment_num_tombstone_updates_downloaded_by(1); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In the event that IDs match, but tags differ AttemptReuniteClient tag 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will have refused to unify the update. 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We should not attempt to apply it at all since it violates consistency 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// rules. 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochVerifyResult VerifyTagConsistency(const SyncEntity& entry, 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::MutableEntry& same_id) { 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry.has_client_defined_unique_tag() && 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.client_defined_unique_tag() != 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch same_id.Get(syncable::UNIQUE_CLIENT_TAG)) { 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return VERIFY_FAIL; 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return VERIFY_UNDECIDED; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochVerifyUpdatesCommand::VerifyUpdateResult VerifyUpdatesCommand::VerifyUpdate( 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::WriteTransaction* trans, const SyncEntity& entry, 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ModelSafeRoutingInfo& routes) { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id id = entry.id(); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VerifyUpdateResult result = {VERIFY_FAIL, GROUP_PASSIVE}; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool deleted = entry.has_deleted() && entry.deleted(); 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool is_directory = entry.IsFolder(); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::ModelType model_type = entry.GetModelType(); 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!id.ServerKnows()) { 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Illegal negative id in received updates"; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string name = SyncerProtoUtil::NameFromSyncEntity(entry); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (name.empty() && !deleted) { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Zero length name in non-deleted update"; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::MutableEntry same_id(trans, GET_BY_ID, id); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result.value = SyncerUtil::VerifyNewEntry(entry, &same_id, deleted); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType placement_type = !deleted ? entry.GetModelType() 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : same_id.good() ? same_id.GetModelType() : syncable::UNSPECIFIED; 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result.placement = GetGroupForModelType(placement_type, routes); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (VERIFY_UNDECIDED == result.value) { 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result.value = VerifyTagConsistency(entry, same_id); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (VERIFY_UNDECIDED == result.value) { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (deleted) 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result.value = VERIFY_SUCCESS; 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we have an existing entry, we check here for updates that break 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // consistency rules. 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (VERIFY_UNDECIDED == result.value) { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result.value = SyncerUtil::VerifyUpdateConsistency(trans, entry, &same_id, 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deleted, is_directory, model_type); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (VERIFY_UNDECIDED == result.value) 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result.value = VERIFY_SUCCESS; // No news is good news. 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; // This might be VERIFY_SUCCESS as well 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace browser_sync 129