12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/engine/apply_control_data_updates.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/engine/conflict_resolver.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/engine/conflict_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/engine/syncer_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/directory.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/mutable_entry.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/nigori_handler.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/nigori_util.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/syncable_write_transaction.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/util/cryptographer.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using syncable::GET_TYPE_ROOT; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::IS_UNAPPLIED_UPDATE; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::IS_UNSYNCED; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::SERVER_SPECIFICS; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::SPECIFICS; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::SYNCER; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ApplyControlDataUpdates(syncable::Directory* dir) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncable::WriteTransaction trans(FROM_HERE, SYNCER, dir); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (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()) { 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) syncable::MutableEntry entry(&trans, syncable::GET_TYPE_ROOT, iter.Get()); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!entry.good()) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (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)); 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!entry.GetUniqueServerTag().empty()) { 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We should have already applied all top level control nodes. 71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (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)); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Update the nigori handler with the server's nigori node. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If we have a locally modified nigori node, we merge them manually. This 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handles the case where two clients both set a different passphrase. The 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// second client to attempt to commit will go into a state of having pending 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// keys, unioned the set of encrypted types, and eventually re-encrypt 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// everything with the passphrase of the first client and commit the set of 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// merged encryption keys. Until the second client provides the pending 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// passphrase, the cryptographer will preserve the encryption keys based on the 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// local passphrase, while the nigori node will preserve the server encryption 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// keys. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ApplyNigoriUpdate(syncable::WriteTransaction* const trans, 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::MutableEntry* const entry, 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Cryptographer* cryptographer) { 95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(entry->GetIsUnappliedUpdate()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We apply the nigori update regardless of whether there's a conflict or 985821806d5e7f356e8fa4b058a389a808ea183019Torne (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. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::NigoriSpecifics& nigori = 103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) entry->GetServerSpecifics().nigori(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans->directory()->GetNigoriHandler()->ApplyNigoriUpdate(nigori, trans); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure any unsynced changes are properly encrypted as necessary. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only perform this if the cryptographer is ready. If not, these are 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // re-encrypted at SetDecryptionPassphrase time (via ReEncryptEverything). 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This logic covers the case where the nigori update marked new datatypes 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for encryption, but didn't change the passphrase. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cryptographer->is_ready()) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we don't bother to encrypt any data for which IS_UNSYNCED 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // == false here. The machine that turned on encryption should know about 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and re-encrypt all synced data. It's possible it could get interrupted 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // during this process, but we currently reencrypt everything at startup 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as well, so as soon as a client is restarted with this datatype marked 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for encryption, all the data should be updated as necessary. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this fails, something is wrong with the cryptographer, but there's 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // nothing we can do about it here. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Received new nigori, encrypting unsynced changes."; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncable::ProcessUnsyncedChangesForEncryption(trans); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!entry->GetIsUnsynced()) { // Update only. 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateLocalDataFromServerData(trans, entry); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // Conflict. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::EntitySpecifics& server_specifics = 129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) entry->GetServerSpecifics(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::NigoriSpecifics& server_nigori = server_specifics.nigori(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::EntitySpecifics& local_specifics = 132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) entry->GetSpecifics(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::NigoriSpecifics& local_nigori = local_specifics.nigori(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We initialize the new nigori with the server state, and will override 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it as necessary below. 137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sync_pb::EntitySpecifics new_specifics = entry->GetServerSpecifics(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::NigoriSpecifics* new_nigori = new_specifics.mutable_nigori(); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the cryptographer is not ready, another client set a new encryption 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // passphrase. If we had migrated locally, we will re-migrate when the 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pending keys are provided. If we had set a new custom passphrase locally 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the user will have another chance to set a custom passphrase later 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (assuming they hadn't set a custom passphrase on the other client). 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Therefore, we only attempt to merge the nigori nodes if the cryptographer 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is ready. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: we only update the encryption keybag if we're sure that we aren't 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invalidating the keystore_decryptor_token (i.e. we're either 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not migrated or we copying over all local state). 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cryptographer->is_ready()) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (local_nigori.has_passphrase_type() && 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_nigori.has_passphrase_type()) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // They're both migrated, preserve the local nigori if the passphrase 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // type is more conservative. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_nigori.passphrase_type() == 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE && 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_nigori.passphrase_type() != 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(local_nigori.passphrase_type() == 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE || 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_nigori.passphrase_type() == 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nigori->CopyFrom(local_nigori); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cryptographer->GetKeys(new_nigori->mutable_encryption_keybag()); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!local_nigori.has_passphrase_type() && 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !server_nigori.has_passphrase_type()) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the explicit passphrase based on the local state. If the server 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // had set an explict passphrase, we should have pending keys, so 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should not reach this code. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Because neither side is migrated, we don't have to worry about the 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // keystore decryptor token. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nigori->set_keybag_is_frozen(local_nigori.keybag_is_frozen()); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cryptographer->GetKeys(new_nigori->mutable_encryption_keybag()); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (local_nigori.has_passphrase_type()) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Local is migrated but server is not. Copy over the local migrated 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nigori->CopyFrom(local_nigori); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cryptographer->GetKeys(new_nigori->mutable_encryption_keybag()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } // else leave the new nigori with the server state. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Always update to the safest set of encrypted types. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans->directory()->GetNigoriHandler()->UpdateNigoriFromEncryptedTypes( 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nigori, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) entry->PutSpecifics(new_specifics); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Resolving simple conflict, merging nigori nodes: " 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << entry; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) conflict_util::OverwriteServerChanges(entry); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict", 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConflictResolver::NIGORI_MERGE, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConflictResolver::CONFLICT_RESOLUTION_SIZE); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (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); 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(entry->GetIsUnappliedUpdate()); 205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (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) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateAttemptResponse response = AttemptToUpdateEntry( 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trans, entry, cryptographer); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(SUCCESS, response); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncer 220