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.
5 #include "base/format_macros.h"
6 #include "base/location.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/stringprintf.h"
9 #include "sync/engine/apply_control_data_updates.h"
10 #include "sync/engine/syncer.h"
11 #include "sync/engine/syncer_util.h"
12 #include "sync/internal_api/public/test/test_entry_factory.h"
13 #include "sync/protocol/nigori_specifics.pb.h"
14 #include "sync/syncable/mutable_entry.h"
15 #include "sync/syncable/nigori_util.h"
16 #include "sync/syncable/read_transaction.h"
17 #include "sync/syncable/syncable_util.h"
18 #include "sync/syncable/write_transaction.h"
19 #include "sync/test/engine/fake_model_worker.h"
20 #include "sync/test/engine/syncer_command_test.h"
21 #include "sync/test/engine/test_id_factory.h"
22 #include "sync/test/fake_sync_encryption_handler.h"
23 #include "sync/util/cryptographer.h"
24 #include "testing/gtest/include/gtest/gtest.h"
28 using syncable::MutableEntry
;
29 using syncable::UNITTEST
;
32 class ApplyControlDataUpdatesTest
: public SyncerCommandTest
{
35 ApplyControlDataUpdatesTest() {}
36 virtual ~ApplyControlDataUpdatesTest() {}
38 virtual void SetUp() {
40 mutable_routing_info()->clear();
41 workers()->push_back(make_scoped_refptr(new FakeModelWorker(GROUP_UI
)));
43 make_scoped_refptr(new FakeModelWorker(GROUP_PASSWORD
)));
44 (*mutable_routing_info())[BOOKMARKS
] = GROUP_UI
;
45 (*mutable_routing_info())[PASSWORDS
] = GROUP_PASSWORD
;
46 (*mutable_routing_info())[NIGORI
] = GROUP_PASSIVE
;
47 SyncerCommandTest::SetUp();
48 entry_factory_
.reset(new TestEntryFactory(directory()));
50 syncable::ReadTransaction
trans(FROM_HERE
, directory());
53 TestIdFactory id_factory_
;
54 scoped_ptr
<TestEntryFactory
> entry_factory_
;
56 DISALLOW_COPY_AND_ASSIGN(ApplyControlDataUpdatesTest
);
59 // Verify that applying a nigori node sets initial sync ended properly,
60 // updates the set of encrypted types, and updates the cryptographer.
61 TEST_F(ApplyControlDataUpdatesTest
, NigoriUpdate
) {
62 // Storing the cryptographer separately is bad, but for this test we
64 Cryptographer
* cryptographer
;
65 ModelTypeSet encrypted_types
;
66 encrypted_types
.PutAll(SyncEncryptionHandler::SensitiveTypes());
68 // We start with initial_sync_ended == false. This is wrong, since we would
69 // have no nigori node if that were the case. However, it makes it easier to
70 // verify that ApplyControlDataUpdates sets initial_sync_ended correctly.
71 EXPECT_FALSE(directory()->initial_sync_ended_types().Has(NIGORI
));
74 syncable::ReadTransaction
trans(FROM_HERE
, directory());
75 cryptographer
= directory()->GetCryptographer(&trans
);
76 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
77 .Equals(encrypted_types
));
80 // Nigori node updates should update the Cryptographer.
81 Cryptographer
other_cryptographer(cryptographer
->encryptor());
82 KeyParams params
= {"localhost", "dummy", "foobar"};
83 other_cryptographer
.AddKey(params
);
85 sync_pb::EntitySpecifics specifics
;
86 sync_pb::NigoriSpecifics
* nigori
= specifics
.mutable_nigori();
87 other_cryptographer
.GetKeys(nigori
->mutable_encryption_keybag());
88 nigori
->set_encrypt_everything(true);
89 entry_factory_
->CreateUnappliedNewItem(
90 ModelTypeToRootTag(NIGORI
), specifics
, true);
91 EXPECT_FALSE(cryptographer
->has_pending_keys());
93 ApplyControlDataUpdates(directory());
95 EXPECT_FALSE(cryptographer
->is_ready());
96 EXPECT_TRUE(cryptographer
->has_pending_keys());
98 syncable::ReadTransaction
trans(FROM_HERE
, directory());
99 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
100 .Equals(ModelTypeSet::All()));
101 EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI
));
105 // Create some local unsynced and unencrypted data. Apply a nigori update that
106 // turns on encryption for the unsynced data. Ensure we properly encrypt the
107 // data as part of the nigori update. Apply another nigori update with no
108 // changes. Ensure we ignore already-encrypted unsynced data and that nothing
110 TEST_F(ApplyControlDataUpdatesTest
, EncryptUnsyncedChanges
) {
111 // Storing the cryptographer separately is bad, but for this test we
113 Cryptographer
* cryptographer
;
114 ModelTypeSet encrypted_types
;
115 encrypted_types
.PutAll(SyncEncryptionHandler::SensitiveTypes());
117 syncable::ReadTransaction
trans(FROM_HERE
, directory());
118 cryptographer
= directory()->GetCryptographer(&trans
);
119 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
120 .Equals(encrypted_types
));
122 // With default encrypted_types, this should be true.
123 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans
, encrypted_types
));
125 Syncer::UnsyncedMetaHandles handles
;
126 GetUnsyncedEntries(&trans
, &handles
);
127 EXPECT_TRUE(handles
.empty());
130 // Create unsynced bookmarks without encryption.
131 // First item is a folder
132 Id folder_id
= id_factory_
.NewLocalId();
133 entry_factory_
->CreateUnsyncedItem(folder_id
, id_factory_
.root(), "folder",
134 true, BOOKMARKS
, NULL
);
135 // Next five items are children of the folder
138 for (i
= 0; i
< batch_s
; ++i
) {
139 entry_factory_
->CreateUnsyncedItem(id_factory_
.NewLocalId(), folder_id
,
140 base::StringPrintf("Item %"PRIuS
"", i
),
141 false, BOOKMARKS
, NULL
);
143 // Next five items are children of the root.
144 for (; i
< 2*batch_s
; ++i
) {
145 entry_factory_
->CreateUnsyncedItem(
146 id_factory_
.NewLocalId(), id_factory_
.root(),
147 base::StringPrintf("Item %"PRIuS
"", i
), false,
151 KeyParams params
= {"localhost", "dummy", "foobar"};
152 cryptographer
->AddKey(params
);
153 sync_pb::EntitySpecifics specifics
;
154 sync_pb::NigoriSpecifics
* nigori
= specifics
.mutable_nigori();
155 cryptographer
->GetKeys(nigori
->mutable_encryption_keybag());
156 nigori
->set_encrypt_everything(true);
157 encrypted_types
.Put(BOOKMARKS
);
158 entry_factory_
->CreateUnappliedNewItem(
159 ModelTypeToRootTag(NIGORI
), specifics
, true);
160 EXPECT_FALSE(cryptographer
->has_pending_keys());
161 EXPECT_TRUE(cryptographer
->is_ready());
164 // Ensure we have unsynced nodes that aren't properly encrypted.
165 syncable::ReadTransaction
trans(FROM_HERE
, directory());
166 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans
, encrypted_types
));
168 Syncer::UnsyncedMetaHandles handles
;
169 GetUnsyncedEntries(&trans
, &handles
);
170 EXPECT_EQ(2*batch_s
+1, handles
.size());
173 ApplyControlDataUpdates(directory());
175 EXPECT_FALSE(cryptographer
->has_pending_keys());
176 EXPECT_TRUE(cryptographer
->is_ready());
178 syncable::ReadTransaction
trans(FROM_HERE
, directory());
180 // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes
181 // should be encrypted now.
182 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
183 .Equals(ModelTypeSet::All()));
184 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans
, encrypted_types
));
186 Syncer::UnsyncedMetaHandles handles
;
187 GetUnsyncedEntries(&trans
, &handles
);
188 EXPECT_EQ(2*batch_s
+1, handles
.size());
191 // Simulate another nigori update that doesn't change anything.
193 syncable::WriteTransaction
trans(FROM_HERE
, UNITTEST
, directory());
194 MutableEntry
entry(&trans
, syncable::GET_BY_SERVER_TAG
,
195 ModelTypeToRootTag(NIGORI
));
196 ASSERT_TRUE(entry
.good());
197 entry
.Put(syncable::SERVER_VERSION
, entry_factory_
->GetNextRevision());
198 entry
.Put(syncable::IS_UNAPPLIED_UPDATE
, true);
201 ApplyControlDataUpdates(directory());
203 EXPECT_FALSE(cryptographer
->has_pending_keys());
204 EXPECT_TRUE(cryptographer
->is_ready());
206 syncable::ReadTransaction
trans(FROM_HERE
, directory());
208 // All our changes should still be encrypted.
209 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
210 .Equals(ModelTypeSet::All()));
211 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans
, encrypted_types
));
213 Syncer::UnsyncedMetaHandles handles
;
214 GetUnsyncedEntries(&trans
, &handles
);
215 EXPECT_EQ(2*batch_s
+1, handles
.size());
219 // Create some local unsynced and unencrypted changes. Receive a new nigori
220 // node enabling their encryption but also introducing pending keys. Ensure
221 // we apply the update properly without encrypting the unsynced changes or
223 TEST_F(ApplyControlDataUpdatesTest
, CannotEncryptUnsyncedChanges
) {
224 // Storing the cryptographer separately is bad, but for this test we
226 Cryptographer
* cryptographer
;
227 ModelTypeSet encrypted_types
;
228 encrypted_types
.PutAll(SyncEncryptionHandler::SensitiveTypes());
230 syncable::ReadTransaction
trans(FROM_HERE
, directory());
231 cryptographer
= directory()->GetCryptographer(&trans
);
232 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
233 .Equals(encrypted_types
));
235 // With default encrypted_types, this should be true.
236 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans
, encrypted_types
));
238 Syncer::UnsyncedMetaHandles handles
;
239 GetUnsyncedEntries(&trans
, &handles
);
240 EXPECT_TRUE(handles
.empty());
243 // Create unsynced bookmarks without encryption.
244 // First item is a folder
245 Id folder_id
= id_factory_
.NewLocalId();
246 entry_factory_
->CreateUnsyncedItem(
247 folder_id
, id_factory_
.root(), "folder", true,
249 // Next five items are children of the folder
252 for (i
= 0; i
< batch_s
; ++i
) {
253 entry_factory_
->CreateUnsyncedItem(id_factory_
.NewLocalId(), folder_id
,
254 base::StringPrintf("Item %"PRIuS
"", i
),
255 false, BOOKMARKS
, NULL
);
257 // Next five items are children of the root.
258 for (; i
< 2*batch_s
; ++i
) {
259 entry_factory_
->CreateUnsyncedItem(
260 id_factory_
.NewLocalId(), id_factory_
.root(),
261 base::StringPrintf("Item %"PRIuS
"", i
), false,
265 // We encrypt with new keys, triggering the local cryptographer to be unready
266 // and unable to decrypt data (once updated).
267 Cryptographer
other_cryptographer(cryptographer
->encryptor());
268 KeyParams params
= {"localhost", "dummy", "foobar"};
269 other_cryptographer
.AddKey(params
);
270 sync_pb::EntitySpecifics specifics
;
271 sync_pb::NigoriSpecifics
* nigori
= specifics
.mutable_nigori();
272 other_cryptographer
.GetKeys(nigori
->mutable_encryption_keybag());
273 nigori
->set_encrypt_everything(true);
274 encrypted_types
.Put(BOOKMARKS
);
275 entry_factory_
->CreateUnappliedNewItem(
276 ModelTypeToRootTag(NIGORI
), specifics
, true);
277 EXPECT_FALSE(cryptographer
->has_pending_keys());
280 // Ensure we have unsynced nodes that aren't properly encrypted.
281 syncable::ReadTransaction
trans(FROM_HERE
, directory());
282 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans
, encrypted_types
));
283 Syncer::UnsyncedMetaHandles handles
;
284 GetUnsyncedEntries(&trans
, &handles
);
285 EXPECT_EQ(2*batch_s
+1, handles
.size());
288 ApplyControlDataUpdates(directory());
290 EXPECT_FALSE(cryptographer
->is_ready());
291 EXPECT_TRUE(cryptographer
->has_pending_keys());
293 syncable::ReadTransaction
trans(FROM_HERE
, directory());
295 // Since we have pending keys, we would have failed to encrypt, but the
296 // cryptographer should be updated.
297 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans
, encrypted_types
));
298 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
299 .Equals(ModelTypeSet::All()));
300 EXPECT_FALSE(cryptographer
->is_ready());
301 EXPECT_TRUE(cryptographer
->has_pending_keys());
303 Syncer::UnsyncedMetaHandles handles
;
304 GetUnsyncedEntries(&trans
, &handles
);
305 EXPECT_EQ(2*batch_s
+1, handles
.size());
309 // Verify we handle a nigori node conflict by merging encryption keys and
310 // types, but preserve the custom passphrase state of the server.
311 // Initial sync ended should be set.
312 TEST_F(ApplyControlDataUpdatesTest
,
313 NigoriConflictPendingKeysServerEncryptEverythingCustom
) {
314 Cryptographer
* cryptographer
;
315 ModelTypeSet
encrypted_types(SyncEncryptionHandler::SensitiveTypes());
316 KeyParams other_params
= {"localhost", "dummy", "foobar"};
317 KeyParams local_params
= {"localhost", "dummy", "local"};
319 syncable::ReadTransaction
trans(FROM_HERE
, directory());
320 cryptographer
= directory()->GetCryptographer(&trans
);
321 EXPECT_TRUE(encrypted_types
.Equals(
322 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)));
325 // Set up a temporary cryptographer to generate new keys with.
326 Cryptographer
other_cryptographer(cryptographer
->encryptor());
327 other_cryptographer
.AddKey(other_params
);
329 // Create server specifics with pending keys, new encrypted types,
330 // and a custom passphrase (unmigrated).
331 sync_pb::EntitySpecifics server_specifics
;
332 sync_pb::NigoriSpecifics
* server_nigori
= server_specifics
.mutable_nigori();
333 other_cryptographer
.GetKeys(server_nigori
->mutable_encryption_keybag());
334 server_nigori
->set_encrypt_everything(true);
335 server_nigori
->set_keybag_is_frozen(true);
336 int64 nigori_handle
=
337 entry_factory_
->CreateUnappliedNewItem(kNigoriTag
,
341 // Initialize the local cryptographer with the local keys.
342 cryptographer
->AddKey(local_params
);
343 EXPECT_TRUE(cryptographer
->is_ready());
345 // Set up a local nigori with the local encryption keys and default encrypted
347 sync_pb::EntitySpecifics local_specifics
;
348 sync_pb::NigoriSpecifics
* local_nigori
= local_specifics
.mutable_nigori();
349 cryptographer
->GetKeys(local_nigori
->mutable_encryption_keybag());
350 local_nigori
->set_encrypt_everything(false);
351 local_nigori
->set_keybag_is_frozen(true);
352 ASSERT_TRUE(entry_factory_
->SetLocalSpecificsForItem(
353 nigori_handle
, local_specifics
));
354 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
357 syncable::ReadTransaction
trans(FROM_HERE
, directory());
358 cryptographer
= directory()->GetCryptographer(&trans
);
359 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
364 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
365 EXPECT_TRUE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
366 ApplyControlDataUpdates(directory());
367 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
368 EXPECT_FALSE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
370 EXPECT_FALSE(cryptographer
->is_ready());
371 EXPECT_TRUE(cryptographer
->is_initialized());
372 EXPECT_TRUE(cryptographer
->has_pending_keys());
373 EXPECT_TRUE(other_cryptographer
.CanDecryptUsingDefaultKey(
374 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
375 nigori().encryption_keybag()));
376 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
377 nigori().keybag_is_frozen());
378 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
379 nigori().encrypt_everything());
381 syncable::ReadTransaction
trans(FROM_HERE
, directory());
382 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
383 .Equals(ModelTypeSet::All()));
384 EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI
));
388 // Verify we handle a nigori node conflict by merging encryption keys and
389 // types, but preserve the custom passphrase state of the server.
390 // Initial sync ended should be set.
391 TEST_F(ApplyControlDataUpdatesTest
,
392 NigoriConflictPendingKeysLocalEncryptEverythingCustom
) {
393 Cryptographer
* cryptographer
;
394 ModelTypeSet
encrypted_types(SyncEncryptionHandler::SensitiveTypes());
395 KeyParams other_params
= {"localhost", "dummy", "foobar"};
396 KeyParams local_params
= {"localhost", "dummy", "local"};
398 syncable::ReadTransaction
trans(FROM_HERE
, directory());
399 cryptographer
= directory()->GetCryptographer(&trans
);
400 EXPECT_TRUE(encrypted_types
.Equals(
401 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)));
404 // Set up a temporary cryptographer to generate new keys with.
405 Cryptographer
other_cryptographer(cryptographer
->encryptor());
406 other_cryptographer
.AddKey(other_params
);
408 // Create server specifics with pending keys, new encrypted types,
409 // and a custom passphrase (unmigrated).
410 sync_pb::EntitySpecifics server_specifics
;
411 sync_pb::NigoriSpecifics
* server_nigori
= server_specifics
.mutable_nigori();
412 other_cryptographer
.GetKeys(server_nigori
->mutable_encryption_keybag());
413 server_nigori
->set_encrypt_everything(false);
414 server_nigori
->set_keybag_is_frozen(false);
415 int64 nigori_handle
=
416 entry_factory_
->CreateUnappliedNewItem(kNigoriTag
,
420 // Initialize the local cryptographer with the local keys.
421 cryptographer
->AddKey(local_params
);
422 EXPECT_TRUE(cryptographer
->is_ready());
424 // Set up a local nigori with the local encryption keys and default encrypted
426 sync_pb::EntitySpecifics local_specifics
;
427 sync_pb::NigoriSpecifics
* local_nigori
= local_specifics
.mutable_nigori();
428 cryptographer
->GetKeys(local_nigori
->mutable_encryption_keybag());
429 local_nigori
->set_encrypt_everything(true);
430 local_nigori
->set_keybag_is_frozen(true);
431 ASSERT_TRUE(entry_factory_
->SetLocalSpecificsForItem(
432 nigori_handle
, local_specifics
));
433 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
436 syncable::ReadTransaction
trans(FROM_HERE
, directory());
437 cryptographer
= directory()->GetCryptographer(&trans
);
438 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
443 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
444 EXPECT_TRUE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
445 ApplyControlDataUpdates(directory());
446 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
447 EXPECT_FALSE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
449 EXPECT_FALSE(cryptographer
->is_ready());
450 EXPECT_TRUE(cryptographer
->is_initialized());
451 EXPECT_TRUE(cryptographer
->has_pending_keys());
452 EXPECT_TRUE(other_cryptographer
.CanDecryptUsingDefaultKey(
453 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
454 nigori().encryption_keybag()));
455 EXPECT_FALSE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
456 nigori().keybag_is_frozen());
457 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
458 nigori().encrypt_everything());
460 syncable::ReadTransaction
trans(FROM_HERE
, directory());
461 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
462 .Equals(ModelTypeSet::All()));
463 EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI
));
467 // If the conflicting nigori has a subset of the local keys, the conflict
468 // resolution should preserve the full local keys. Initial sync ended should be
470 TEST_F(ApplyControlDataUpdatesTest
,
471 NigoriConflictOldKeys
) {
472 Cryptographer
* cryptographer
;
473 ModelTypeSet
encrypted_types(SyncEncryptionHandler::SensitiveTypes());
474 KeyParams old_params
= {"localhost", "dummy", "old"};
475 KeyParams new_params
= {"localhost", "dummy", "new"};
477 syncable::ReadTransaction
trans(FROM_HERE
, directory());
478 cryptographer
= directory()->GetCryptographer(&trans
);
479 EXPECT_TRUE(encrypted_types
.Equals(
480 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)));
483 // Set up the cryptographer with old keys
484 cryptographer
->AddKey(old_params
);
486 // Create server specifics with old keys and new encrypted types.
487 sync_pb::EntitySpecifics server_specifics
;
488 sync_pb::NigoriSpecifics
* server_nigori
= server_specifics
.mutable_nigori();
489 cryptographer
->GetKeys(server_nigori
->mutable_encryption_keybag());
490 server_nigori
->set_encrypt_everything(true);
491 int64 nigori_handle
=
492 entry_factory_
->CreateUnappliedNewItem(kNigoriTag
,
496 // Add the new keys to the cryptogrpaher
497 cryptographer
->AddKey(new_params
);
498 EXPECT_TRUE(cryptographer
->is_ready());
500 // Set up a local nigori with the superset of keys.
501 sync_pb::EntitySpecifics local_specifics
;
502 sync_pb::NigoriSpecifics
* local_nigori
= local_specifics
.mutable_nigori();
503 cryptographer
->GetKeys(local_nigori
->mutable_encryption_keybag());
504 local_nigori
->set_encrypt_everything(false);
505 ASSERT_TRUE(entry_factory_
->SetLocalSpecificsForItem(
506 nigori_handle
, local_specifics
));
507 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
510 syncable::ReadTransaction
trans(FROM_HERE
, directory());
511 cryptographer
= directory()->GetCryptographer(&trans
);
512 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
517 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
518 EXPECT_TRUE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
519 ApplyControlDataUpdates(directory());
520 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
521 EXPECT_FALSE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
523 EXPECT_TRUE(cryptographer
->is_ready());
524 EXPECT_TRUE(cryptographer
->CanDecryptUsingDefaultKey(
525 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
526 nigori().encryption_keybag()));
527 EXPECT_FALSE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
528 nigori().keybag_is_frozen());
529 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
530 nigori().encrypt_everything());
532 syncable::ReadTransaction
trans(FROM_HERE
, directory());
533 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
534 .Equals(ModelTypeSet::All()));
535 EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI
));
539 // If both nigoris are migrated, but we also set a custom passphrase locally,
540 // the local nigori should be preserved.
541 TEST_F(ApplyControlDataUpdatesTest
,
542 NigoriConflictBothMigratedLocalCustom
) {
543 Cryptographer
* cryptographer
;
544 ModelTypeSet
encrypted_types(SyncEncryptionHandler::SensitiveTypes());
545 KeyParams old_params
= {"localhost", "dummy", "old"};
546 KeyParams new_params
= {"localhost", "dummy", "new"};
548 syncable::ReadTransaction
trans(FROM_HERE
, directory());
549 cryptographer
= directory()->GetCryptographer(&trans
);
550 EXPECT_TRUE(encrypted_types
.Equals(
551 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)));
554 // Set up the cryptographer with new keys
555 Cryptographer
other_cryptographer(cryptographer
->encryptor());
556 other_cryptographer
.AddKey(old_params
);
558 // Create server specifics with a migrated keystore passphrase type.
559 sync_pb::EntitySpecifics server_specifics
;
560 sync_pb::NigoriSpecifics
* server_nigori
= server_specifics
.mutable_nigori();
561 other_cryptographer
.GetKeys(server_nigori
->mutable_encryption_keybag());
562 server_nigori
->set_encrypt_everything(false);
563 server_nigori
->set_keybag_is_frozen(true);
564 server_nigori
->set_passphrase_type(
565 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE
);
566 server_nigori
->mutable_keystore_decryptor_token();
567 int64 nigori_handle
=
568 entry_factory_
->CreateUnappliedNewItem(kNigoriTag
,
572 // Add the new keys to the cryptographer.
573 cryptographer
->AddKey(old_params
);
574 cryptographer
->AddKey(new_params
);
575 EXPECT_TRUE(cryptographer
->is_ready());
577 // Set up a local nigori with a migrated custom passphrase type
578 sync_pb::EntitySpecifics local_specifics
;
579 sync_pb::NigoriSpecifics
* local_nigori
= local_specifics
.mutable_nigori();
580 cryptographer
->GetKeys(local_nigori
->mutable_encryption_keybag());
581 local_nigori
->set_encrypt_everything(true);
582 local_nigori
->set_keybag_is_frozen(true);
583 local_nigori
->set_passphrase_type(
584 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE
);
585 ASSERT_TRUE(entry_factory_
->SetLocalSpecificsForItem(
586 nigori_handle
, local_specifics
));
587 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
590 syncable::ReadTransaction
trans(FROM_HERE
, directory());
591 cryptographer
= directory()->GetCryptographer(&trans
);
592 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
597 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
598 EXPECT_TRUE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
599 ApplyControlDataUpdates(directory());
600 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
601 EXPECT_FALSE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
603 EXPECT_TRUE(cryptographer
->is_ready());
604 EXPECT_TRUE(cryptographer
->CanDecryptUsingDefaultKey(
605 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
606 nigori().encryption_keybag()));
607 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
608 nigori().keybag_is_frozen());
609 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
610 nigori().encrypt_everything());
611 EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE
,
612 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
613 nigori().passphrase_type());
615 syncable::ReadTransaction
trans(FROM_HERE
, directory());
616 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
617 .Equals(ModelTypeSet::All()));
618 EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI
));
622 // If both nigoris are migrated, but a custom passphrase with a new key was
623 // set remotely, the remote nigori should be preserved.
624 TEST_F(ApplyControlDataUpdatesTest
,
625 NigoriConflictBothMigratedServerCustom
) {
626 Cryptographer
* cryptographer
;
627 ModelTypeSet
encrypted_types(SyncEncryptionHandler::SensitiveTypes());
628 KeyParams old_params
= {"localhost", "dummy", "old"};
629 KeyParams new_params
= {"localhost", "dummy", "new"};
631 syncable::ReadTransaction
trans(FROM_HERE
, directory());
632 cryptographer
= directory()->GetCryptographer(&trans
);
633 EXPECT_TRUE(encrypted_types
.Equals(
634 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)));
637 // Set up the cryptographer with both new keys and old keys.
638 Cryptographer
other_cryptographer(cryptographer
->encryptor());
639 other_cryptographer
.AddKey(old_params
);
640 other_cryptographer
.AddKey(new_params
);
642 // Create server specifics with a migrated custom passphrase type.
643 sync_pb::EntitySpecifics server_specifics
;
644 sync_pb::NigoriSpecifics
* server_nigori
= server_specifics
.mutable_nigori();
645 other_cryptographer
.GetKeys(server_nigori
->mutable_encryption_keybag());
646 server_nigori
->set_encrypt_everything(true);
647 server_nigori
->set_keybag_is_frozen(true);
648 server_nigori
->set_passphrase_type(
649 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE
);
650 int64 nigori_handle
=
651 entry_factory_
->CreateUnappliedNewItem(kNigoriTag
,
655 // Add the old keys to the cryptographer.
656 cryptographer
->AddKey(old_params
);
657 EXPECT_TRUE(cryptographer
->is_ready());
659 // Set up a local nigori with a migrated keystore passphrase type
660 sync_pb::EntitySpecifics local_specifics
;
661 sync_pb::NigoriSpecifics
* local_nigori
= local_specifics
.mutable_nigori();
662 cryptographer
->GetKeys(local_nigori
->mutable_encryption_keybag());
663 local_nigori
->set_encrypt_everything(false);
664 local_nigori
->set_keybag_is_frozen(true);
665 local_nigori
->set_passphrase_type(
666 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE
);
667 server_nigori
->mutable_keystore_decryptor_token();
668 ASSERT_TRUE(entry_factory_
->SetLocalSpecificsForItem(
669 nigori_handle
, local_specifics
));
670 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
673 syncable::ReadTransaction
trans(FROM_HERE
, directory());
674 cryptographer
= directory()->GetCryptographer(&trans
);
675 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
680 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
681 EXPECT_TRUE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
682 ApplyControlDataUpdates(directory());
683 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
684 EXPECT_FALSE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
686 EXPECT_TRUE(cryptographer
->is_initialized());
687 EXPECT_TRUE(cryptographer
->has_pending_keys());
688 EXPECT_TRUE(other_cryptographer
.CanDecryptUsingDefaultKey(
689 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
690 nigori().encryption_keybag()));
691 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
692 nigori().keybag_is_frozen());
693 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
694 nigori().encrypt_everything());
695 EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE
,
696 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
697 nigori().passphrase_type());
699 syncable::ReadTransaction
trans(FROM_HERE
, directory());
700 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
701 .Equals(ModelTypeSet::All()));
702 EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI
));
706 // If the local nigori is migrated but the server is not, preserve the local
708 TEST_F(ApplyControlDataUpdatesTest
,
709 NigoriConflictLocalMigrated
) {
710 Cryptographer
* cryptographer
;
711 ModelTypeSet
encrypted_types(SyncEncryptionHandler::SensitiveTypes());
712 KeyParams old_params
= {"localhost", "dummy", "old"};
713 KeyParams new_params
= {"localhost", "dummy", "new"};
715 syncable::ReadTransaction
trans(FROM_HERE
, directory());
716 cryptographer
= directory()->GetCryptographer(&trans
);
717 EXPECT_TRUE(encrypted_types
.Equals(
718 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)));
721 // Set up the cryptographer with both new keys and old keys.
722 Cryptographer
other_cryptographer(cryptographer
->encryptor());
723 other_cryptographer
.AddKey(old_params
);
725 // Create server specifics with an unmigrated implicit passphrase type.
726 sync_pb::EntitySpecifics server_specifics
;
727 sync_pb::NigoriSpecifics
* server_nigori
= server_specifics
.mutable_nigori();
728 other_cryptographer
.GetKeys(server_nigori
->mutable_encryption_keybag());
729 server_nigori
->set_encrypt_everything(true);
730 server_nigori
->set_keybag_is_frozen(false);
731 int64 nigori_handle
=
732 entry_factory_
->CreateUnappliedNewItem(kNigoriTag
,
736 // Add the old keys to the cryptographer.
737 cryptographer
->AddKey(old_params
);
738 cryptographer
->AddKey(new_params
);
739 EXPECT_TRUE(cryptographer
->is_ready());
741 // Set up a local nigori with a migrated custom passphrase type
742 sync_pb::EntitySpecifics local_specifics
;
743 sync_pb::NigoriSpecifics
* local_nigori
= local_specifics
.mutable_nigori();
744 cryptographer
->GetKeys(local_nigori
->mutable_encryption_keybag());
745 local_nigori
->set_encrypt_everything(true);
746 local_nigori
->set_keybag_is_frozen(true);
747 local_nigori
->set_passphrase_type(
748 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE
);
749 ASSERT_TRUE(entry_factory_
->SetLocalSpecificsForItem(
750 nigori_handle
, local_specifics
));
751 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
754 syncable::ReadTransaction
trans(FROM_HERE
, directory());
755 cryptographer
= directory()->GetCryptographer(&trans
);
756 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
761 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
762 EXPECT_TRUE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
763 ApplyControlDataUpdates(directory());
764 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
765 EXPECT_FALSE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
767 EXPECT_TRUE(cryptographer
->is_ready());
768 EXPECT_TRUE(cryptographer
->CanDecryptUsingDefaultKey(
769 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
770 nigori().encryption_keybag()));
771 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
772 nigori().keybag_is_frozen());
773 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
774 nigori().encrypt_everything());
775 EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE
,
776 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
777 nigori().passphrase_type());
779 syncable::ReadTransaction
trans(FROM_HERE
, directory());
780 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)
781 .Equals(ModelTypeSet::All()));
782 EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI
));
786 // If the server nigori is migrated but the local is not, preserve the server
788 TEST_F(ApplyControlDataUpdatesTest
,
789 NigoriConflictServerMigrated
) {
790 Cryptographer
* cryptographer
;
791 ModelTypeSet
encrypted_types(SyncEncryptionHandler::SensitiveTypes());
792 KeyParams old_params
= {"localhost", "dummy", "old"};
793 KeyParams new_params
= {"localhost", "dummy", "new"};
795 syncable::ReadTransaction
trans(FROM_HERE
, directory());
796 cryptographer
= directory()->GetCryptographer(&trans
);
797 EXPECT_TRUE(encrypted_types
.Equals(
798 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans
)));
801 // Set up the cryptographer with both new keys and old keys.
802 Cryptographer
other_cryptographer(cryptographer
->encryptor());
803 other_cryptographer
.AddKey(old_params
);
805 // Create server specifics with an migrated keystore passphrase type.
806 sync_pb::EntitySpecifics server_specifics
;
807 sync_pb::NigoriSpecifics
* server_nigori
= server_specifics
.mutable_nigori();
808 other_cryptographer
.GetKeys(server_nigori
->mutable_encryption_keybag());
809 server_nigori
->set_encrypt_everything(false);
810 server_nigori
->set_keybag_is_frozen(true);
811 server_nigori
->set_passphrase_type(
812 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE
);
813 server_nigori
->mutable_keystore_decryptor_token();
814 int64 nigori_handle
=
815 entry_factory_
->CreateUnappliedNewItem(kNigoriTag
,
819 // Add the old keys to the cryptographer.
820 cryptographer
->AddKey(old_params
);
821 cryptographer
->AddKey(new_params
);
822 EXPECT_TRUE(cryptographer
->is_ready());
824 // Set up a local nigori with a migrated custom passphrase type
825 sync_pb::EntitySpecifics local_specifics
;
826 sync_pb::NigoriSpecifics
* local_nigori
= local_specifics
.mutable_nigori();
827 cryptographer
->GetKeys(local_nigori
->mutable_encryption_keybag());
828 local_nigori
->set_encrypt_everything(false);
829 local_nigori
->set_keybag_is_frozen(false);
830 ASSERT_TRUE(entry_factory_
->SetLocalSpecificsForItem(
831 nigori_handle
, local_specifics
));
832 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
835 syncable::ReadTransaction
trans(FROM_HERE
, directory());
836 cryptographer
= directory()->GetCryptographer(&trans
);
837 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
842 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
843 EXPECT_TRUE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
844 ApplyControlDataUpdates(directory());
845 EXPECT_TRUE(entry_factory_
->GetIsUnsyncedForItem(nigori_handle
));
846 EXPECT_FALSE(entry_factory_
->GetIsUnappliedForItem(nigori_handle
));
848 EXPECT_TRUE(cryptographer
->is_ready());
849 // Note: we didn't overwrite the encryption keybag with the local keys. The
850 // sync encryption handler will do that when it detects that the new
851 // keybag is out of date (and update the keystore bootstrap if necessary).
852 EXPECT_FALSE(cryptographer
->CanDecryptUsingDefaultKey(
853 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
854 nigori().encryption_keybag()));
855 EXPECT_TRUE(cryptographer
->CanDecrypt(
856 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
857 nigori().encryption_keybag()));
858 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
859 nigori().keybag_is_frozen());
860 EXPECT_TRUE(entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
861 nigori().has_keystore_decryptor_token());
862 EXPECT_EQ(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE
,
863 entry_factory_
->GetLocalSpecificsForItem(nigori_handle
).
864 nigori().passphrase_type());
866 syncable::ReadTransaction
trans(FROM_HERE
, directory());
867 EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI
));
871 } // namespace syncer