diff options
Diffstat (limited to 'chromium/sync/engine/apply_control_data_updates.cc')
-rw-r--r-- | chromium/sync/engine/apply_control_data_updates.cc | 221 |
1 files changed, 0 insertions, 221 deletions
diff --git a/chromium/sync/engine/apply_control_data_updates.cc b/chromium/sync/engine/apply_control_data_updates.cc deleted file mode 100644 index e97741ed336..00000000000 --- a/chromium/sync/engine/apply_control_data_updates.cc +++ /dev/null @@ -1,221 +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/apply_control_data_updates.h" - -#include "base/metrics/histogram.h" -#include "sync/engine/conflict_resolver.h" -#include "sync/engine/conflict_util.h" -#include "sync/engine/syncer_util.h" -#include "sync/syncable/directory.h" -#include "sync/syncable/mutable_entry.h" -#include "sync/syncable/nigori_handler.h" -#include "sync/syncable/nigori_util.h" -#include "sync/syncable/syncable_write_transaction.h" -#include "sync/util/cryptographer.h" - -namespace syncer { - -using syncable::GET_BY_SERVER_TAG; -using syncable::IS_UNAPPLIED_UPDATE; -using syncable::IS_UNSYNCED; -using syncable::SERVER_SPECIFICS; -using syncable::SPECIFICS; -using syncable::SYNCER; - -void ApplyControlDataUpdates(syncable::Directory* dir) { - syncable::WriteTransaction trans(FROM_HERE, SYNCER, dir); - - std::vector<int64> handles; - dir->GetUnappliedUpdateMetaHandles( - &trans, ToFullModelTypeSet(ControlTypes()), &handles); - - // First, go through and manually apply any new top level datatype nodes (so - // that we don't have to worry about hitting a CONFLICT_HIERARCHY with an - // entry because we haven't applied its parent yet). - // TODO(sync): if at some point we support control datatypes with actual - // hierarchies we'll need to revisit this logic. - ModelTypeSet control_types = ControlTypes(); - for (ModelTypeSet::Iterator iter = control_types.First(); iter.Good(); - iter.Inc()) { - syncable::MutableEntry entry(&trans, - syncable::GET_BY_SERVER_TAG, - ModelTypeToRootTag(iter.Get())); - if (!entry.good()) - continue; - if (!entry.GetIsUnappliedUpdate()) - continue; - - ModelType type = entry.GetServerModelType(); - if (type == NIGORI) { - // Nigori node applications never fail. - ApplyNigoriUpdate(&trans, - &entry, - dir->GetCryptographer(&trans)); - } else { - ApplyControlUpdate(&trans, - &entry, - dir->GetCryptographer(&trans)); - } - } - - // Go through the rest of the unapplied control updates, skipping over any - // top level folders. - for (std::vector<int64>::const_iterator iter = handles.begin(); - iter != handles.end(); ++iter) { - syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, *iter); - CHECK(entry.good()); - ModelType type = entry.GetServerModelType(); - CHECK(ControlTypes().Has(type)); - if (!entry.GetUniqueServerTag().empty()) { - // We should have already applied all top level control nodes. - DCHECK(!entry.GetIsUnappliedUpdate()); - continue; - } - - ApplyControlUpdate(&trans, - &entry, - dir->GetCryptographer(&trans)); - } -} - -// Update the nigori handler with the server's nigori node. -// -// If we have a locally modified nigori node, we merge them manually. This -// handles the case where two clients both set a different passphrase. The -// second client to attempt to commit will go into a state of having pending -// keys, unioned the set of encrypted types, and eventually re-encrypt -// everything with the passphrase of the first client and commit the set of -// merged encryption keys. Until the second client provides the pending -// passphrase, the cryptographer will preserve the encryption keys based on the -// local passphrase, while the nigori node will preserve the server encryption -// keys. -void ApplyNigoriUpdate(syncable::WriteTransaction* const trans, - syncable::MutableEntry* const entry, - Cryptographer* cryptographer) { - DCHECK(entry->GetIsUnappliedUpdate()); - - // We apply the nigori update regardless of whether there's a conflict or - // not in order to preserve any new encrypted types or encryption keys. - // TODO(zea): consider having this return a bool reflecting whether it was a - // valid update or not, and in the case of invalid updates not overwrite the - // local data. - const sync_pb::NigoriSpecifics& nigori = - entry->GetServerSpecifics().nigori(); - trans->directory()->GetNigoriHandler()->ApplyNigoriUpdate(nigori, trans); - - // Make sure any unsynced changes are properly encrypted as necessary. - // We only perform this if the cryptographer is ready. If not, these are - // re-encrypted at SetDecryptionPassphrase time (via ReEncryptEverything). - // This logic covers the case where the nigori update marked new datatypes - // for encryption, but didn't change the passphrase. - if (cryptographer->is_ready()) { - // Note that we don't bother to encrypt any data for which IS_UNSYNCED - // == false here. The machine that turned on encryption should know about - // and re-encrypt all synced data. It's possible it could get interrupted - // during this process, but we currently reencrypt everything at startup - // as well, so as soon as a client is restarted with this datatype marked - // for encryption, all the data should be updated as necessary. - - // If this fails, something is wrong with the cryptographer, but there's - // nothing we can do about it here. - DVLOG(1) << "Received new nigori, encrypting unsynced changes."; - syncable::ProcessUnsyncedChangesForEncryption(trans); - } - - if (!entry->GetIsUnsynced()) { // Update only. - UpdateLocalDataFromServerData(trans, entry); - } else { // Conflict. - const sync_pb::EntitySpecifics& server_specifics = - entry->GetServerSpecifics(); - const sync_pb::NigoriSpecifics& server_nigori = server_specifics.nigori(); - const sync_pb::EntitySpecifics& local_specifics = - entry->GetSpecifics(); - const sync_pb::NigoriSpecifics& local_nigori = local_specifics.nigori(); - - // We initialize the new nigori with the server state, and will override - // it as necessary below. - sync_pb::EntitySpecifics new_specifics = entry->GetServerSpecifics(); - sync_pb::NigoriSpecifics* new_nigori = new_specifics.mutable_nigori(); - - // If the cryptographer is not ready, another client set a new encryption - // passphrase. If we had migrated locally, we will re-migrate when the - // pending keys are provided. If we had set a new custom passphrase locally - // the user will have another chance to set a custom passphrase later - // (assuming they hadn't set a custom passphrase on the other client). - // Therefore, we only attempt to merge the nigori nodes if the cryptographer - // is ready. - // Note: we only update the encryption keybag if we're sure that we aren't - // invalidating the keystore_decryptor_token (i.e. we're either - // not migrated or we copying over all local state). - if (cryptographer->is_ready()) { - if (local_nigori.has_passphrase_type() && - server_nigori.has_passphrase_type()) { - // They're both migrated, preserve the local nigori if the passphrase - // type is more conservative. - if (server_nigori.passphrase_type() == - sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE && - local_nigori.passphrase_type() != - sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) { - DCHECK(local_nigori.passphrase_type() == - sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE || - local_nigori.passphrase_type() == - sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE); - new_nigori->CopyFrom(local_nigori); - cryptographer->GetKeys(new_nigori->mutable_encryption_keybag()); - } - } else if (!local_nigori.has_passphrase_type() && - !server_nigori.has_passphrase_type()) { - // Set the explicit passphrase based on the local state. If the server - // had set an explict passphrase, we should have pending keys, so - // should not reach this code. - // Because neither side is migrated, we don't have to worry about the - // keystore decryptor token. - new_nigori->set_keybag_is_frozen(local_nigori.keybag_is_frozen()); - cryptographer->GetKeys(new_nigori->mutable_encryption_keybag()); - } else if (local_nigori.has_passphrase_type()) { - // Local is migrated but server is not. Copy over the local migrated - // data. - new_nigori->CopyFrom(local_nigori); - cryptographer->GetKeys(new_nigori->mutable_encryption_keybag()); - } // else leave the new nigori with the server state. - } - - // Always update to the safest set of encrypted types. - trans->directory()->GetNigoriHandler()->UpdateNigoriFromEncryptedTypes( - new_nigori, - trans); - - entry->PutSpecifics(new_specifics); - DVLOG(1) << "Resolving simple conflict, merging nigori nodes: " - << entry; - - conflict_util::OverwriteServerChanges(entry); - - UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict", - ConflictResolver::NIGORI_MERGE, - ConflictResolver::CONFLICT_RESOLUTION_SIZE); - } -} - -void ApplyControlUpdate(syncable::WriteTransaction* const trans, - syncable::MutableEntry* const entry, - Cryptographer* cryptographer) { - DCHECK_NE(entry->GetServerModelType(), NIGORI); - DCHECK(entry->GetIsUnappliedUpdate()); - if (entry->GetIsUnsynced()) { - // We just let the server win all conflicts with control types. - DVLOG(1) << "Ignoring local changes for control update."; - conflict_util::IgnoreLocalChanges(entry); - UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict", - ConflictResolver::OVERWRITE_LOCAL, - ConflictResolver::CONFLICT_RESOLUTION_SIZE); - } - - UpdateAttemptResponse response = AttemptToUpdateEntry( - trans, entry, cryptographer); - DCHECK_EQ(SUCCESS, response); -} - -} // namespace syncer |