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

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

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

Powered by Google App Engine
This is Rietveld 408576698