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

Side by Side Diff: sync/engine/apply_metadata_updates.cc

Issue 10559104: sync: Process 'control' data separately (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update patch. Still draft quality. Created 8 years, 6 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #include "sync/engine/apply_metadata_updates.h"
2
3 #include "base/metrics/histogram.h"
4 #include "sync/engine/conflict_resolver.h" // For the ConflictResolution enums F IXME
5 #include "sync/engine/nigori_util.h"
6 #include "sync/engine/syncer_util.h"
7 #include "sync/syncable/directory.h"
8 #include "sync/syncable/mutable_entry.h"
9 #include "sync/syncable/write_transaction.h"
10 #include "sync/util/cryptographer.h"
11
12 using syncable::GET_BY_SERVER_TAG;
13 using syncable::IS_UNAPPLIED_UPDATE;
14 using syncable::IS_UNSYNCED;
15 using syncable::NIGORI;
16 using syncable::SERVER_SPECIFICS;
17 using syncable::SPECIFICS;
18 using syncable::SYNCER;
19
20 namespace browser_sync {
21
22 void ApplyMetadataUpdates(syncable::Directory* dir) {
23 syncable::WriteTransaction trans(FROM_HERE, SYNCER, dir);
24 ApplyNigoriUpdates(&trans, dir->GetCryptographer(&trans));
25 }
26
27 void ApplyNigoriUpdates(syncable::WriteTransaction* trans,
28 Cryptographer* cryptographer) {
29 syncable::MutableEntry nigori_node(trans, GET_BY_SERVER_TAG,
30 ModelTypeToRootTag(NIGORI));
31
32 // Mainly for unit tests. We should have a Nigori node by this point.
33 if (!nigori_node.good()) {
34 return;
35 }
36
37 // We always update the cryptographer with the server's nigori node,
38 // even if we have a locally modified nigori node (we manually merge nigori
39 // data in the conflict resolver in that case). This handles the case where
40 // two clients both set a different passphrase. The second client to attempt
41 // to commit will go into a state of having pending keys, unioned the set of
42 // encrypted types, and eventually re-encrypt everything with the passphrase
43 // of the first client and commit the set of merged encryption keys. Until the
44 // second client provides the pending passphrase, the cryptographer will
45 // preserve the encryption keys based on the local passphrase, while the
46 // nigori node will preserve the server encryption keys.
47 //
48 // If non-encryption changes are made to the nigori node, they will be
49 // lost as part of conflict resolution. This is intended, as we place a higher
50 // priority on preserving the server's passphrase change to preserving local
51 // non-encryption changes. Next time the non-encryption changes are made to
52 // the nigori node (e.g. on restart), they will commit without issue.
53 if (nigori_node.Get(IS_UNAPPLIED_UPDATE)) {
Nicolas Zea 2012/06/21 02:58:36 if (!nigori_node.Get(IS_UNAPPLIED_UPDATE)) retur
54 const sync_pb::NigoriSpecifics& nigori =
55 nigori_node.Get(SERVER_SPECIFICS).nigori();
56 cryptographer->Update(nigori);
57
58 // Make sure any unsynced changes are properly encrypted as necessary.
59 // We only perform this if the cryptographer is ready. If not, these are
60 // re-encrypted at SetDecryptionPassphrase time (via ReEncryptEverything).
61 // This logic covers the case where the nigori update marked new datatypes
62 // for encryption, but didn't change the passphrase.
63 if (cryptographer->is_ready()) {
64 // Note that we don't bother to encrypt any data for which IS_UNSYNCED
65 // == false here. The machine that turned on encryption should know about
66 // and re-encrypt all synced data. It's possible it could get interrupted
67 // during this process, but we currently reencrypt everything at startup
68 // as well, so as soon as a client is restarted with this datatype marked
69 // for encryption, all the data should be updated as necessary.
70
71 // If this fails, something is wrong with the cryptographer, but there's
72 // nothing we can do about it here.
73 DVLOG(1) << "Received new nigori, encrypting unsynced changes.";
74 syncable::ProcessUnsyncedChangesForEncryption(trans, cryptographer);
75 }
76
77 if (!nigori_node.Get(IS_UNSYNCED)) { // Update only.
78 SyncerUtil::UpdateLocalDataFromServerData(trans, &nigori_node);
79 } else { // Conflict.
80 // Create a new set of specifics based on the server specifics (which
81 // preserves their encryption keys).
82 sync_pb::EntitySpecifics specifics = nigori_node.Get(SERVER_SPECIFICS);
83 sync_pb::NigoriSpecifics* server_nigori = specifics.mutable_nigori();
84 // Store the merged set of encrypted types (cryptographer->Update(..) will
85 // have merged the local types already).
86 cryptographer->UpdateNigoriFromEncryptedTypes(server_nigori);
87 // The cryptographer has the both the local and remote encryption keys
88 // (added at cryptographer->Update(..) time).
89 // If the cryptographer is ready, then it already merged both sets of keys
90 // and we can store them back in. In that case, the remote key was already
91 // part of the local keybag, so we preserve the local key as the default
92 // (including whether it's an explicit key).
93 // If the cryptographer is not ready, then the user will have to provide
94 // the passphrase to decrypt the pending keys. When they do so, the
95 // SetDecryptionPassphrase code will act based on whether the server
96 // update has an explicit passphrase or not.
97 // - If the server had an explicit passphrase, that explicit passphrase
98 // will be preserved as the default encryption key.
99 // - If the server did not have an explicit passphrase, we assume the
100 // local passphrase is the most up to date and preserve the local
101 // default encryption key marked as an implicit passphrase.
102 // This works fine except for the case where we had locally set an
103 // explicit passphrase. In that case the nigori node will have the default
104 // key based on the local explicit passphassphrase, but will not have it
105 // marked as explicit. To fix this we'd have to track whether we have a
106 // explicit passphrase or not separate from the nigori, which would
107 // introduce even more complexity, so we leave it up to the user to reset
108 // that passphrase as an explicit one via settings. The goal here is to
109 // ensure both sets of encryption keys are preserved.
110 if (cryptographer->is_ready()) {
111 cryptographer->GetKeys(server_nigori->mutable_encrypted());
112 server_nigori->set_using_explicit_passphrase(
113 nigori_node.Get(SPECIFICS).nigori().
114 using_explicit_passphrase());
115 }
116 // We deliberately leave the server's device information. This client will
117 // add its own device information on restart.
118 nigori_node.Put(SPECIFICS, specifics);
119 DVLOG(1) << "Resolving simple conflict, merging nigori nodes: "
120 << nigori_node;
121
122 SyncerUtil::OverwriteServerChanges(&nigori_node);
123
124 UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
125 ConflictResolver::NIGORI_MERGE,
126 ConflictResolver::CONFLICT_RESOLUTION_SIZE);
127 }
128 }
129 }
130
131 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698