12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "sync/engine/apply_control_data_updates.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/engine/conflict_resolver.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/engine/conflict_util.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/engine/syncer_util.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/directory.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/mutable_entry.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/nigori_handler.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/nigori_util.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/syncable_write_transaction.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/util/cryptographer.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace syncer { 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using syncable::GET_TYPE_ROOT; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using syncable::IS_UNAPPLIED_UPDATE; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using syncable::IS_UNSYNCED; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using syncable::SERVER_SPECIFICS; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using syncable::SPECIFICS; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using syncable::SYNCER; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ApplyControlDataUpdates(syncable::Directory* dir) { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::WriteTransaction trans(FROM_HERE, SYNCER, dir); 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<int64> handles; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dir->GetUnappliedUpdateMetaHandles( 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &trans, ToFullModelTypeSet(ControlTypes()), &handles); 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // First, go through and manually apply any new top level datatype nodes (so 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that we don't have to worry about hitting a CONFLICT_HIERARCHY with an 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // entry because we haven't applied its parent yet). 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(sync): if at some point we support control datatypes with actual 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // hierarchies we'll need to revisit this logic. 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelTypeSet control_types = ControlTypes(); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ModelTypeSet::Iterator iter = control_types.First(); iter.Good(); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter.Inc()) { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::MutableEntry entry(&trans, syncable::GET_TYPE_ROOT, iter.Get()); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!entry.good()) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!entry.GetIsUnappliedUpdate()) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelType type = entry.GetServerModelType(); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (type == NIGORI) { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Nigori node applications never fail. 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ApplyNigoriUpdate(&trans, 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &entry, 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dir->GetCryptographer(&trans)); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ApplyControlUpdate(&trans, 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &entry, 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dir->GetCryptographer(&trans)); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Go through the rest of the unapplied control updates, skipping over any 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // top level folders. 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<int64>::const_iterator iter = handles.begin(); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != handles.end(); ++iter) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, *iter); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(entry.good()); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelType type = entry.GetServerModelType(); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(ControlTypes().Has(type)); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!entry.GetUniqueServerTag().empty()) { 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We should have already applied all top level control nodes. 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!entry.GetIsUnappliedUpdate()); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ApplyControlUpdate(&trans, 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &entry, 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dir->GetCryptographer(&trans)); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Update the nigori handler with the server's nigori node. 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// If we have a locally modified nigori node, we merge them manually. This 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// handles the case where two clients both set a different passphrase. The 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// second client to attempt to commit will go into a state of having pending 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// keys, unioned the set of encrypted types, and eventually re-encrypt 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// everything with the passphrase of the first client and commit the set of 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// merged encryption keys. Until the second client provides the pending 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// passphrase, the cryptographer will preserve the encryption keys based on the 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// local passphrase, while the nigori node will preserve the server encryption 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// keys. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ApplyNigoriUpdate(syncable::WriteTransaction* const trans, 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::MutableEntry* const entry, 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Cryptographer* cryptographer) { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(entry->GetIsUnappliedUpdate()); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We apply the nigori update regardless of whether there's a conflict or 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not in order to preserve any new encrypted types or encryption keys. 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): consider having this return a bool reflecting whether it was a 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // valid update or not, and in the case of invalid updates not overwrite the 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // local data. 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const sync_pb::NigoriSpecifics& nigori = 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry->GetServerSpecifics().nigori(); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trans->directory()->GetNigoriHandler()->ApplyNigoriUpdate(nigori, trans); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure any unsynced changes are properly encrypted as necessary. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We only perform this if the cryptographer is ready. If not, these are 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // re-encrypted at SetDecryptionPassphrase time (via ReEncryptEverything). 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This logic covers the case where the nigori update marked new datatypes 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for encryption, but didn't change the passphrase. 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cryptographer->is_ready()) { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note that we don't bother to encrypt any data for which IS_UNSYNCED 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // == false here. The machine that turned on encryption should know about 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and re-encrypt all synced data. It's possible it could get interrupted 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // during this process, but we currently reencrypt everything at startup 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // as well, so as soon as a client is restarted with this datatype marked 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for encryption, all the data should be updated as necessary. 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If this fails, something is wrong with the cryptographer, but there's 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // nothing we can do about it here. 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Received new nigori, encrypting unsynced changes."; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::ProcessUnsyncedChangesForEncryption(trans); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!entry->GetIsUnsynced()) { // Update only. 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateLocalDataFromServerData(trans, entry); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { // Conflict. 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const sync_pb::EntitySpecifics& server_specifics = 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry->GetServerSpecifics(); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const sync_pb::NigoriSpecifics& server_nigori = server_specifics.nigori(); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const sync_pb::EntitySpecifics& local_specifics = 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry->GetSpecifics(); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const sync_pb::NigoriSpecifics& local_nigori = local_specifics.nigori(); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We initialize the new nigori with the server state, and will override 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it as necessary below. 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::EntitySpecifics new_specifics = entry->GetServerSpecifics(); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::NigoriSpecifics* new_nigori = new_specifics.mutable_nigori(); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the cryptographer is not ready, another client set a new encryption 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // passphrase. If we had migrated locally, we will re-migrate when the 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // pending keys are provided. If we had set a new custom passphrase locally 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the user will have another chance to set a custom passphrase later 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (assuming they hadn't set a custom passphrase on the other client). 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Therefore, we only attempt to merge the nigori nodes if the cryptographer 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is ready. 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: we only update the encryption keybag if we're sure that we aren't 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // invalidating the keystore_decryptor_token (i.e. we're either 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not migrated or we copying over all local state). 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cryptographer->is_ready()) { 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (local_nigori.has_passphrase_type() && 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_nigori.has_passphrase_type()) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // They're both migrated, preserve the local nigori if the passphrase 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // type is more conservative. 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (server_nigori.passphrase_type() == 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE && 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_nigori.passphrase_type() != 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) { 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(local_nigori.passphrase_type() == 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE || 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_nigori.passphrase_type() == 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_nigori->CopyFrom(local_nigori); 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cryptographer->GetKeys(new_nigori->mutable_encryption_keybag()); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (!local_nigori.has_passphrase_type() && 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !server_nigori.has_passphrase_type()) { 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set the explicit passphrase based on the local state. If the server 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // had set an explict passphrase, we should have pending keys, so 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // should not reach this code. 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Because neither side is migrated, we don't have to worry about the 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // keystore decryptor token. 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_nigori->set_keybag_is_frozen(local_nigori.keybag_is_frozen()); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cryptographer->GetKeys(new_nigori->mutable_encryption_keybag()); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (local_nigori.has_passphrase_type()) { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Local is migrated but server is not. Copy over the local migrated 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // data. 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_nigori->CopyFrom(local_nigori); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cryptographer->GetKeys(new_nigori->mutable_encryption_keybag()); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } // else leave the new nigori with the server state. 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Always update to the safest set of encrypted types. 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trans->directory()->GetNigoriHandler()->UpdateNigoriFromEncryptedTypes( 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_nigori, 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trans); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry->PutSpecifics(new_specifics); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Resolving simple conflict, merging nigori nodes: " 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << entry; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) conflict_util::OverwriteServerChanges(entry); 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict", 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConflictResolver::NIGORI_MERGE, 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConflictResolver::CONFLICT_RESOLUTION_SIZE); 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ApplyControlUpdate(syncable::WriteTransaction* const trans, 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::MutableEntry* const entry, 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Cryptographer* cryptographer) { 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(entry->GetServerModelType(), NIGORI); 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(entry->GetIsUnappliedUpdate()); 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry->GetIsUnsynced()) { 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We just let the server win all conflicts with control types. 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Ignoring local changes for control update."; 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) conflict_util::IgnoreLocalChanges(entry); 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict", 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConflictResolver::OVERWRITE_LOCAL, 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConflictResolver::CONFLICT_RESOLUTION_SIZE); 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateAttemptResponse response = AttemptToUpdateEntry( 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trans, entry, cryptographer); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(SUCCESS, response); 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace syncer 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)