// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #include "chrome/browser/sync/engine/verify_updates_command.h" #include "chrome/browser/sync/engine/syncer.h" #include "chrome/browser/sync/engine/syncer_proto_util.h" #include "chrome/browser/sync/engine/syncer_types.h" #include "chrome/browser/sync/engine/syncer_util.h" #include "chrome/browser/sync/engine/syncproto.h" #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" #include "chrome/browser/sync/syncable/directory_manager.h" #include "chrome/browser/sync/syncable/syncable.h" namespace browser_sync { using syncable::ScopedDirLookup; using syncable::SyncName; using syncable::WriteTransaction; using syncable::GET_BY_ID; using syncable::SYNCER; VerifyUpdatesCommand::VerifyUpdatesCommand() {} VerifyUpdatesCommand::~VerifyUpdatesCommand() {} void VerifyUpdatesCommand::ModelChangingExecuteImpl( sessions::SyncSession* session) { VLOG(1) << "Beginning Update Verification"; ScopedDirLookup dir(session->context()->directory_manager(), session->context()->account_name()); if (!dir.good()) { LOG(ERROR) << "Scoped dir lookup failed!"; return; } WriteTransaction trans(dir, SYNCER, __FILE__, __LINE__); sessions::StatusController* status = session->status_controller(); const GetUpdatesResponse& updates = status->updates_response().get_updates(); int update_count = updates.entries().size(); VLOG(1) << update_count << " entries to verify"; for (int i = 0; i < update_count; i++) { const SyncEntity& update = *reinterpret_cast<const SyncEntity *>(&(updates.entries(i))); ModelSafeGroup g = GetGroupForModelType(update.GetModelType(), session->routing_info()); if (g != status->group_restriction()) continue; VerifyUpdateResult result = VerifyUpdate(&trans, update, session->routing_info()); status->mutable_update_progress()->AddVerifyResult(result.value, update); status->increment_num_updates_downloaded_by(1); if (update.deleted()) status->increment_num_tombstone_updates_downloaded_by(1); } } namespace { // In the event that IDs match, but tags differ AttemptReuniteClient tag // will have refused to unify the update. // We should not attempt to apply it at all since it violates consistency // rules. VerifyResult VerifyTagConsistency(const SyncEntity& entry, const syncable::MutableEntry& same_id) { if (entry.has_client_defined_unique_tag() && entry.client_defined_unique_tag() != same_id.Get(syncable::UNIQUE_CLIENT_TAG)) { return VERIFY_FAIL; } return VERIFY_UNDECIDED; } } // namespace VerifyUpdatesCommand::VerifyUpdateResult VerifyUpdatesCommand::VerifyUpdate( syncable::WriteTransaction* trans, const SyncEntity& entry, const ModelSafeRoutingInfo& routes) { syncable::Id id = entry.id(); VerifyUpdateResult result = {VERIFY_FAIL, GROUP_PASSIVE}; const bool deleted = entry.has_deleted() && entry.deleted(); const bool is_directory = entry.IsFolder(); const syncable::ModelType model_type = entry.GetModelType(); if (!id.ServerKnows()) { LOG(ERROR) << "Illegal negative id in received updates"; return result; } { const std::string name = SyncerProtoUtil::NameFromSyncEntity(entry); if (name.empty() && !deleted) { LOG(ERROR) << "Zero length name in non-deleted update"; return result; } } syncable::MutableEntry same_id(trans, GET_BY_ID, id); result.value = SyncerUtil::VerifyNewEntry(entry, &same_id, deleted); syncable::ModelType placement_type = !deleted ? entry.GetModelType() : same_id.good() ? same_id.GetModelType() : syncable::UNSPECIFIED; result.placement = GetGroupForModelType(placement_type, routes); if (VERIFY_UNDECIDED == result.value) { result.value = VerifyTagConsistency(entry, same_id); } if (VERIFY_UNDECIDED == result.value) { if (deleted) result.value = VERIFY_SUCCESS; } // If we have an existing entry, we check here for updates that break // consistency rules. if (VERIFY_UNDECIDED == result.value) { result.value = SyncerUtil::VerifyUpdateConsistency(trans, entry, &same_id, deleted, is_directory, model_type); } if (VERIFY_UNDECIDED == result.value) result.value = VERIFY_SUCCESS; // No news is good news. return result; // This might be VERIFY_SUCCESS as well } } // namespace browser_sync