More bring up of ui code on iOS.
[chromium-blink-merge.git] / sync / engine / apply_control_data_updates_unittest.cc
blobaa00865be8bb65a279583764708203364db7398e
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"
26 namespace syncer {
28 using syncable::MutableEntry;
29 using syncable::UNITTEST;
30 using syncable::Id;
32 class ApplyControlDataUpdatesTest : public SyncerCommandTest {
33 public:
34 protected:
35 ApplyControlDataUpdatesTest() {}
36 virtual ~ApplyControlDataUpdatesTest() {}
38 virtual void SetUp() {
39 workers()->clear();
40 mutable_routing_info()->clear();
41 workers()->push_back(make_scoped_refptr(new FakeModelWorker(GROUP_UI)));
42 workers()->push_back(
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_;
55 private:
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
63 // know it's safe.
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
109 // breaks.
110 TEST_F(ApplyControlDataUpdatesTest, EncryptUnsyncedChanges) {
111 // Storing the cryptographer separately is bad, but for this test we
112 // know it's safe.
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
136 size_t i;
137 size_t batch_s = 5;
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,
148 BOOKMARKS, NULL);
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
222 // breaking.
223 TEST_F(ApplyControlDataUpdatesTest, CannotEncryptUnsyncedChanges) {
224 // Storing the cryptographer separately is bad, but for this test we
225 // know it's safe.
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,
248 BOOKMARKS, NULL);
249 // Next five items are children of the folder
250 size_t i;
251 size_t batch_s = 5;
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,
262 BOOKMARKS, NULL);
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,
338 server_specifics,
339 true);
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
346 // types.
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
355 // to use.
357 syncable::ReadTransaction trans(FROM_HERE, directory());
358 cryptographer = directory()->GetCryptographer(&trans);
359 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
360 *local_nigori,
361 &trans);
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,
417 server_specifics,
418 true);
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
425 // types.
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
434 // to use.
436 syncable::ReadTransaction trans(FROM_HERE, directory());
437 cryptographer = directory()->GetCryptographer(&trans);
438 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
439 *local_nigori,
440 &trans);
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
469 // set.
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,
493 server_specifics,
494 true);
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
508 // to use.
510 syncable::ReadTransaction trans(FROM_HERE, directory());
511 cryptographer = directory()->GetCryptographer(&trans);
512 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
513 *local_nigori,
514 &trans);
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,
569 server_specifics,
570 true);
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
588 // to use.
590 syncable::ReadTransaction trans(FROM_HERE, directory());
591 cryptographer = directory()->GetCryptographer(&trans);
592 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
593 *local_nigori,
594 &trans);
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,
652 server_specifics,
653 true);
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
671 // to use.
673 syncable::ReadTransaction trans(FROM_HERE, directory());
674 cryptographer = directory()->GetCryptographer(&trans);
675 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
676 *local_nigori,
677 &trans);
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
707 // nigori.
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,
733 server_specifics,
734 true);
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
752 // to use.
754 syncable::ReadTransaction trans(FROM_HERE, directory());
755 cryptographer = directory()->GetCryptographer(&trans);
756 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
757 *local_nigori,
758 &trans);
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
787 // nigori.
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,
816 server_specifics,
817 true);
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
833 // to use.
835 syncable::ReadTransaction trans(FROM_HERE, directory());
836 cryptographer = directory()->GetCryptographer(&trans);
837 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
838 *local_nigori,
839 &trans);
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