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

Unified Diff: sync/engine/conflict_resolver.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sync/engine/conflict_resolver.h ('k') | sync/engine/conflict_util.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sync/engine/conflict_resolver.cc
diff --git a/sync/engine/conflict_resolver.cc b/sync/engine/conflict_resolver.cc
deleted file mode 100644
index d32460c5f29a67810871ed2b8cf1cac76f6e21e7..0000000000000000000000000000000000000000
--- a/sync/engine/conflict_resolver.cc
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright 2012 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 "sync/engine/conflict_resolver.h"
-
-#include <list>
-#include <set>
-#include <string>
-
-#include "base/metrics/histogram.h"
-#include "sync/engine/conflict_util.h"
-#include "sync/engine/syncer_util.h"
-#include "sync/internal_api/public/sessions/update_counters.h"
-#include "sync/sessions/status_controller.h"
-#include "sync/syncable/directory.h"
-#include "sync/syncable/mutable_entry.h"
-#include "sync/syncable/syncable_write_transaction.h"
-#include "sync/util/cryptographer.h"
-
-using std::list;
-using std::set;
-
-namespace syncer {
-
-using sessions::StatusController;
-using syncable::Directory;
-using syncable::Entry;
-using syncable::Id;
-using syncable::MutableEntry;
-using syncable::WriteTransaction;
-
-namespace {
-
-// Returns true iff the set of attachment ids contained in attachment_metadata
-// matches the set of ids contained in server_attachment_metadata.
-bool AttachmentMetadataMatches(const MutableEntry& entity) {
- const sync_pb::AttachmentMetadata& local = entity.GetAttachmentMetadata();
- const sync_pb::AttachmentMetadata& server =
- entity.GetServerAttachmentMetadata();
- if (local.record_size() != server.record_size()) {
- return false;
- }
-
- // The order of records in local and server may be different so use a std::set
- // to determine if they are equivalent.
- std::set<std::string> local_ids;
- for (int i = 0; i < local.record_size(); ++i) {
- const sync_pb::AttachmentMetadataRecord& record = local.record(i);
- DCHECK(record.is_on_server());
- local_ids.insert(record.id().SerializeAsString());
- }
- for (int i = 0; i < server.record_size(); ++i) {
- const sync_pb::AttachmentMetadataRecord& record = server.record(i);
- DCHECK(record.is_on_server());
- if (local_ids.find(record.id().SerializeAsString()) == local_ids.end()) {
- return false;
- }
- }
-
- return true;
-}
-
-} // namespace
-
-ConflictResolver::ConflictResolver() {
-}
-
-ConflictResolver::~ConflictResolver() {
-}
-
-void ConflictResolver::ProcessSimpleConflict(WriteTransaction* trans,
- const Id& id,
- const Cryptographer* cryptographer,
- StatusController* status,
- UpdateCounters* counters) {
- MutableEntry entry(trans, syncable::GET_BY_ID, id);
- // Must be good as the entry won't have been cleaned up.
- CHECK(entry.good());
-
- // This function can only resolve simple conflicts. Simple conflicts have
- // both IS_UNSYNCED and IS_UNAPPLIED_UDPATE set.
- if (!entry.GetIsUnappliedUpdate() || !entry.GetIsUnsynced()) {
- // This is very unusual, but it can happen in tests. We may be able to
- // assert NOTREACHED() here when those tests are updated.
- return;
- }
-
- if (entry.GetIsDel() && entry.GetServerIsDel()) {
- // we've both deleted it, so lets just drop the need to commit/update this
- // entry.
- entry.PutIsUnsynced(false);
- entry.PutIsUnappliedUpdate(false);
- // we've made changes, but they won't help syncing progress.
- // METRIC simple conflict resolved by merge.
- return;
- }
-
- // This logic determines "client wins" vs. "server wins" strategy picking.
- // By the time we get to this point, we rely on the following to be true:
- // a) We can decrypt both the local and server data (else we'd be in
- // conflict encryption and not attempting to resolve).
- // b) All unsynced changes have been re-encrypted with the default key (
- // occurs either in AttemptToUpdateEntry, SetEncryptionPassphrase,
- // SetDecryptionPassphrase, or RefreshEncryption).
- // c) Base_server_specifics having a valid datatype means that we received
- // an undecryptable update that only changed specifics, and since then have
- // not received any further non-specifics-only or decryptable updates.
- // d) If the server_specifics match specifics, server_specifics are
- // encrypted with the default key, and all other visible properties match,
- // then we can safely ignore the local changes as redundant.
- // e) Otherwise if the base_server_specifics match the server_specifics, no
- // functional change must have been made server-side (else
- // base_server_specifics would have been cleared), and we can therefore
- // safely ignore the server changes as redundant.
- // f) Otherwise, it's in general safer to ignore local changes, with the
- // exception of deletion conflicts (choose to undelete) and conflicts
- // where the non_unique_name or parent don't match.
- // e) Except for the case of extensions and apps, where we want uninstalls to
- // win over local modifications to avoid "back from the dead" reinstalls.
- if (!entry.GetServerIsDel()) {
- // TODO(nick): The current logic is arbitrary; instead, it ought to be made
- // consistent with the ModelAssociator behavior for a datatype. It would
- // be nice if we could route this back to ModelAssociator code to pick one
- // of three options: CLIENT, SERVER, or MERGE. Some datatypes (autofill)
- // are easily mergeable.
- // See http://crbug.com/77339.
- bool name_matches = entry.GetNonUniqueName() ==
- entry.GetServerNonUniqueName();
- // The parent is implicit type root folder or the parent ID matches.
- bool parent_matches = entry.GetServerParentId().IsNull() ||
- entry.GetParentId() == entry.GetServerParentId();
- bool entry_deleted = entry.GetIsDel();
- // The position check might fail spuriously if one of the positions was
- // based on a legacy random suffix, rather than a deterministic one based on
- // originator_cache_guid and originator_item_id. If an item is being
- // modified regularly, it shouldn't take long for the suffix and position to
- // be updated, so such false failures shouldn't be a problem for long.
- //
- // Lucky for us, it's OK to be wrong here. The position_matches check is
- // allowed to return false negatives, as long as it returns no false
- // positives.
- bool position_matches = parent_matches &&
- entry.GetServerUniquePosition().Equals(entry.GetUniquePosition());
- const sync_pb::EntitySpecifics& specifics = entry.GetSpecifics();
- const sync_pb::EntitySpecifics& server_specifics =
- entry.GetServerSpecifics();
- const sync_pb::EntitySpecifics& base_server_specifics =
- entry.GetBaseServerSpecifics();
- std::string decrypted_specifics, decrypted_server_specifics;
- bool specifics_match = false;
- bool server_encrypted_with_default_key = false;
- if (specifics.has_encrypted()) {
- DCHECK(cryptographer->CanDecryptUsingDefaultKey(specifics.encrypted()));
- decrypted_specifics = cryptographer->DecryptToString(
- specifics.encrypted());
- } else {
- decrypted_specifics = specifics.SerializeAsString();
- }
- if (server_specifics.has_encrypted()) {
- server_encrypted_with_default_key =
- cryptographer->CanDecryptUsingDefaultKey(
- server_specifics.encrypted());
- decrypted_server_specifics = cryptographer->DecryptToString(
- server_specifics.encrypted());
- } else {
- decrypted_server_specifics = server_specifics.SerializeAsString();
- }
- if (decrypted_server_specifics == decrypted_specifics &&
- server_encrypted_with_default_key == specifics.has_encrypted()) {
- specifics_match = true;
- }
- bool base_server_specifics_match = false;
- if (server_specifics.has_encrypted() &&
- IsRealDataType(GetModelTypeFromSpecifics(base_server_specifics))) {
- std::string decrypted_base_server_specifics;
- if (!base_server_specifics.has_encrypted()) {
- decrypted_base_server_specifics =
- base_server_specifics.SerializeAsString();
- } else {
- decrypted_base_server_specifics = cryptographer->DecryptToString(
- base_server_specifics.encrypted());
- }
- if (decrypted_server_specifics == decrypted_base_server_specifics)
- base_server_specifics_match = true;
- }
-
- bool attachment_metadata_matches = AttachmentMetadataMatches(entry);
- if (!entry_deleted && name_matches && parent_matches && specifics_match &&
- position_matches && attachment_metadata_matches) {
- DVLOG(1) << "Resolving simple conflict, everything matches, ignoring "
- << "changes for: " << entry;
- conflict_util::IgnoreConflict(&entry);
- UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
- CHANGES_MATCH,
- CONFLICT_RESOLUTION_SIZE);
- } else if (base_server_specifics_match) {
- DVLOG(1) << "Resolving simple conflict, ignoring server encryption "
- << " changes for: " << entry;
- status->increment_num_server_overwrites();
- counters->num_server_overwrites++;
- conflict_util::OverwriteServerChanges(&entry);
- UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
- IGNORE_ENCRYPTION,
- CONFLICT_RESOLUTION_SIZE);
- } else if (entry_deleted || !name_matches || !parent_matches) {
- // NOTE: The update application logic assumes that conflict resolution
- // will never result in changes to the local hierarchy. The entry_deleted
- // and !parent_matches cases here are critical to maintaining that
- // assumption.
- conflict_util::OverwriteServerChanges(&entry);
- status->increment_num_server_overwrites();
- counters->num_server_overwrites++;
- DVLOG(1) << "Resolving simple conflict, overwriting server changes "
- << "for: " << entry;
- UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
- OVERWRITE_SERVER,
- CONFLICT_RESOLUTION_SIZE);
- } else {
- DVLOG(1) << "Resolving simple conflict, ignoring local changes for: "
- << entry;
- conflict_util::IgnoreLocalChanges(&entry);
- status->increment_num_local_overwrites();
- counters->num_local_overwrites++;
- UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
- OVERWRITE_LOCAL,
- CONFLICT_RESOLUTION_SIZE);
- }
- // Now that we've resolved the conflict, clear the prev server
- // specifics.
- entry.PutBaseServerSpecifics(sync_pb::EntitySpecifics());
- } else { // SERVER_IS_DEL is true
- ModelType type = entry.GetModelType();
- if (type == EXTENSIONS || type == APPS) {
- // Ignore local changes for extensions/apps when server had a delete, to
- // avoid unwanted reinstall of an uninstalled extension.
- DVLOG(1) << "Resolving simple conflict, ignoring local changes for "
- << "extension/app: " << entry;
- conflict_util::IgnoreLocalChanges(&entry);
- status->increment_num_local_overwrites();
- counters->num_local_overwrites++;
- UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
- OVERWRITE_LOCAL,
- CONFLICT_RESOLUTION_SIZE);
- } else {
- if (entry.GetIsDir()) {
- Directory::Metahandles children;
- trans->directory()->GetChildHandlesById(trans,
- entry.GetId(),
- &children);
- // If a server deleted folder has local contents it should be a
- // hierarchy conflict. Hierarchy conflicts should not be processed by
- // this function.
- DCHECK(children.empty());
- }
-
- // The entry is deleted on the server but still exists locally.
- // We undelete it by overwriting the server's tombstone with the local
- // data.
- conflict_util::OverwriteServerChanges(&entry);
- status->increment_num_server_overwrites();
- counters->num_server_overwrites++;
- DVLOG(1) << "Resolving simple conflict, undeleting server entry: "
- << entry;
- UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
- UNDELETE,
- CONFLICT_RESOLUTION_SIZE);
- }
- }
-}
-
-void ConflictResolver::ResolveConflicts(
- syncable::WriteTransaction* trans,
- const Cryptographer* cryptographer,
- const std::set<syncable::Id>& simple_conflict_ids,
- sessions::StatusController* status,
- UpdateCounters* counters) {
- // Iterate over simple conflict items.
- set<Id>::const_iterator it;
- for (it = simple_conflict_ids.begin();
- it != simple_conflict_ids.end();
- ++it) {
- // We don't resolve conflicts for control types here.
- Entry conflicting_node(trans, syncable::GET_BY_ID, *it);
- CHECK(conflicting_node.good());
- if (IsControlType(
- GetModelTypeFromSpecifics(conflicting_node.GetSpecifics()))) {
- continue;
- }
-
- ProcessSimpleConflict(trans, *it, cryptographer, status, counters);
- }
- return;
-}
-
-} // namespace syncer
« no previous file with comments | « sync/engine/conflict_resolver.h ('k') | sync/engine/conflict_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698