Add an exponential backoff to rechecking the app list doodle.
[chromium-blink-merge.git] / sync / engine / apply_control_data_updates_unittest.cc
blob7ed6bd4899f0604a3044f142743cc43b7cf3ed7e
1 // Copyright 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/message_loop/message_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "sync/engine/apply_control_data_updates.h"
11 #include "sync/engine/syncer.h"
12 #include "sync/engine/syncer_util.h"
13 #include "sync/internal_api/public/test/test_entry_factory.h"
14 #include "sync/protocol/nigori_specifics.pb.h"
15 #include "sync/syncable/directory.h"
16 #include "sync/syncable/mutable_entry.h"
17 #include "sync/syncable/nigori_util.h"
18 #include "sync/syncable/syncable_read_transaction.h"
19 #include "sync/syncable/syncable_util.h"
20 #include "sync/syncable/syncable_write_transaction.h"
21 #include "sync/test/engine/fake_model_worker.h"
22 #include "sync/test/engine/test_directory_setter_upper.h"
23 #include "sync/test/engine/test_id_factory.h"
24 #include "sync/test/fake_sync_encryption_handler.h"
25 #include "sync/util/cryptographer.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 namespace syncer {
30 using syncable::MutableEntry;
31 using syncable::UNITTEST;
32 using syncable::Id;
34 class ApplyControlDataUpdatesTest : public ::testing::Test {
35 public:
36 protected:
37 ApplyControlDataUpdatesTest() {}
38 ~ApplyControlDataUpdatesTest() override {}
40 void SetUp() override {
41 dir_maker_.SetUp();
42 entry_factory_.reset(new TestEntryFactory(directory()));
45 void TearDown() override { dir_maker_.TearDown(); }
47 syncable::Directory* directory() {
48 return dir_maker_.directory();
51 TestIdFactory id_factory_;
52 scoped_ptr<TestEntryFactory> entry_factory_;
53 private:
54 base::MessageLoop loop_; // Needed for directory init.
55 TestDirectorySetterUpper dir_maker_;
57 DISALLOW_COPY_AND_ASSIGN(ApplyControlDataUpdatesTest);
60 // Verify that applying a nigori node sets initial sync ended properly,
61 // updates the set of encrypted types, and updates the cryptographer.
62 TEST_F(ApplyControlDataUpdatesTest, NigoriUpdate) {
63 // Storing the cryptographer separately is bad, but for this test we
64 // know it's safe.
65 Cryptographer* cryptographer;
66 ModelTypeSet encrypted_types;
67 encrypted_types.PutAll(SyncEncryptionHandler::SensitiveTypes());
70 syncable::ReadTransaction trans(FROM_HERE, directory());
71 cryptographer = directory()->GetCryptographer(&trans);
72 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
73 .Equals(encrypted_types));
76 // Nigori node updates should update the Cryptographer.
77 Cryptographer other_cryptographer(cryptographer->encryptor());
78 KeyParams params = {"localhost", "dummy", "foobar"};
79 other_cryptographer.AddKey(params);
81 sync_pb::EntitySpecifics specifics;
82 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
83 other_cryptographer.GetKeys(nigori->mutable_encryption_keybag());
84 nigori->set_encrypt_everything(true);
85 entry_factory_->CreateUnappliedNewItem(
86 ModelTypeToRootTag(NIGORI), specifics, true);
87 EXPECT_FALSE(cryptographer->has_pending_keys());
89 ApplyControlDataUpdates(directory());
91 EXPECT_FALSE(cryptographer->is_ready());
92 EXPECT_TRUE(cryptographer->has_pending_keys());
94 syncable::ReadTransaction trans(FROM_HERE, directory());
95 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
96 .Equals(ModelTypeSet::All()));
100 // Create some local unsynced and unencrypted data. Apply a nigori update that
101 // turns on encryption for the unsynced data. Ensure we properly encrypt the
102 // data as part of the nigori update. Apply another nigori update with no
103 // changes. Ensure we ignore already-encrypted unsynced data and that nothing
104 // breaks.
105 TEST_F(ApplyControlDataUpdatesTest, EncryptUnsyncedChanges) {
106 // Storing the cryptographer separately is bad, but for this test we
107 // know it's safe.
108 Cryptographer* cryptographer;
109 ModelTypeSet encrypted_types;
110 encrypted_types.PutAll(SyncEncryptionHandler::SensitiveTypes());
112 syncable::ReadTransaction trans(FROM_HERE, directory());
113 cryptographer = directory()->GetCryptographer(&trans);
114 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
115 .Equals(encrypted_types));
117 // With default encrypted_types, this should be true.
118 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
120 Syncer::UnsyncedMetaHandles handles;
121 GetUnsyncedEntries(&trans, &handles);
122 EXPECT_TRUE(handles.empty());
125 // Create unsynced bookmarks without encryption.
126 // First item is a folder
127 Id folder_id = id_factory_.NewLocalId();
128 entry_factory_->CreateUnsyncedItem(folder_id, id_factory_.root(), "folder",
129 true, BOOKMARKS, NULL);
130 // Next five items are children of the folder
131 size_t i;
132 size_t batch_s = 5;
133 for (i = 0; i < batch_s; ++i) {
134 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
135 base::StringPrintf("Item %" PRIuS "", i),
136 false, BOOKMARKS, NULL);
138 // Next five items are children of the root.
139 for (; i < 2*batch_s; ++i) {
140 entry_factory_->CreateUnsyncedItem(
141 id_factory_.NewLocalId(), id_factory_.root(),
142 base::StringPrintf("Item %" PRIuS "", i), false,
143 BOOKMARKS, NULL);
146 KeyParams params = {"localhost", "dummy", "foobar"};
147 cryptographer->AddKey(params);
148 sync_pb::EntitySpecifics specifics;
149 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
150 cryptographer->GetKeys(nigori->mutable_encryption_keybag());
151 nigori->set_encrypt_everything(true);
152 encrypted_types.Put(BOOKMARKS);
153 entry_factory_->CreateUnappliedNewItem(
154 ModelTypeToRootTag(NIGORI), specifics, true);
155 EXPECT_FALSE(cryptographer->has_pending_keys());
156 EXPECT_TRUE(cryptographer->is_ready());
159 // Ensure we have unsynced nodes that aren't properly encrypted.
160 syncable::ReadTransaction trans(FROM_HERE, directory());
161 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
163 Syncer::UnsyncedMetaHandles handles;
164 GetUnsyncedEntries(&trans, &handles);
165 EXPECT_EQ(2*batch_s+1, handles.size());
168 ApplyControlDataUpdates(directory());
170 EXPECT_FALSE(cryptographer->has_pending_keys());
171 EXPECT_TRUE(cryptographer->is_ready());
173 syncable::ReadTransaction trans(FROM_HERE, directory());
175 // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes
176 // should be encrypted now.
177 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
178 .Equals(ModelTypeSet::All()));
179 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
181 Syncer::UnsyncedMetaHandles handles;
182 GetUnsyncedEntries(&trans, &handles);
183 EXPECT_EQ(2*batch_s+1, handles.size());
186 // Simulate another nigori update that doesn't change anything.
188 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory());
189 MutableEntry entry(&trans, syncable::GET_TYPE_ROOT, NIGORI);
190 ASSERT_TRUE(entry.good());
191 entry.PutServerVersion(entry_factory_->GetNextRevision());
192 entry.PutIsUnappliedUpdate(true);
195 ApplyControlDataUpdates(directory());
197 EXPECT_FALSE(cryptographer->has_pending_keys());
198 EXPECT_TRUE(cryptographer->is_ready());
200 syncable::ReadTransaction trans(FROM_HERE, directory());
202 // All our changes should still be encrypted.
203 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
204 .Equals(ModelTypeSet::All()));
205 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
207 Syncer::UnsyncedMetaHandles handles;
208 GetUnsyncedEntries(&trans, &handles);
209 EXPECT_EQ(2*batch_s+1, handles.size());
213 // Create some local unsynced and unencrypted changes. Receive a new nigori
214 // node enabling their encryption but also introducing pending keys. Ensure
215 // we apply the update properly without encrypting the unsynced changes or
216 // breaking.
217 TEST_F(ApplyControlDataUpdatesTest, CannotEncryptUnsyncedChanges) {
218 // Storing the cryptographer separately is bad, but for this test we
219 // know it's safe.
220 Cryptographer* cryptographer;
221 ModelTypeSet encrypted_types;
222 encrypted_types.PutAll(SyncEncryptionHandler::SensitiveTypes());
224 syncable::ReadTransaction trans(FROM_HERE, directory());
225 cryptographer = directory()->GetCryptographer(&trans);
226 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
227 .Equals(encrypted_types));
229 // With default encrypted_types, this should be true.
230 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
232 Syncer::UnsyncedMetaHandles handles;
233 GetUnsyncedEntries(&trans, &handles);
234 EXPECT_TRUE(handles.empty());
237 // Create unsynced bookmarks without encryption.
238 // First item is a folder
239 Id folder_id = id_factory_.NewLocalId();
240 entry_factory_->CreateUnsyncedItem(
241 folder_id, id_factory_.root(), "folder", true,
242 BOOKMARKS, NULL);
243 // Next five items are children of the folder
244 size_t i;
245 size_t batch_s = 5;
246 for (i = 0; i < batch_s; ++i) {
247 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
248 base::StringPrintf("Item %" PRIuS "", i),
249 false, BOOKMARKS, NULL);
251 // Next five items are children of the root.
252 for (; i < 2*batch_s; ++i) {
253 entry_factory_->CreateUnsyncedItem(
254 id_factory_.NewLocalId(), id_factory_.root(),
255 base::StringPrintf("Item %" PRIuS "", i), false,
256 BOOKMARKS, NULL);
259 // We encrypt with new keys, triggering the local cryptographer to be unready
260 // and unable to decrypt data (once updated).
261 Cryptographer other_cryptographer(cryptographer->encryptor());
262 KeyParams params = {"localhost", "dummy", "foobar"};
263 other_cryptographer.AddKey(params);
264 sync_pb::EntitySpecifics specifics;
265 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
266 other_cryptographer.GetKeys(nigori->mutable_encryption_keybag());
267 nigori->set_encrypt_everything(true);
268 encrypted_types.Put(BOOKMARKS);
269 entry_factory_->CreateUnappliedNewItem(
270 ModelTypeToRootTag(NIGORI), specifics, true);
271 EXPECT_FALSE(cryptographer->has_pending_keys());
274 // Ensure we have unsynced nodes that aren't properly encrypted.
275 syncable::ReadTransaction trans(FROM_HERE, directory());
276 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
277 Syncer::UnsyncedMetaHandles handles;
278 GetUnsyncedEntries(&trans, &handles);
279 EXPECT_EQ(2*batch_s+1, handles.size());
282 ApplyControlDataUpdates(directory());
284 EXPECT_FALSE(cryptographer->is_ready());
285 EXPECT_TRUE(cryptographer->has_pending_keys());
287 syncable::ReadTransaction trans(FROM_HERE, directory());
289 // Since we have pending keys, we would have failed to encrypt, but the
290 // cryptographer should be updated.
291 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
292 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
293 .Equals(ModelTypeSet::All()));
294 EXPECT_FALSE(cryptographer->is_ready());
295 EXPECT_TRUE(cryptographer->has_pending_keys());
297 Syncer::UnsyncedMetaHandles handles;
298 GetUnsyncedEntries(&trans, &handles);
299 EXPECT_EQ(2*batch_s+1, handles.size());
303 // Verify we handle a nigori node conflict by merging encryption keys and
304 // types, but preserve the custom passphrase state of the server.
305 // Initial sync ended should be set.
306 TEST_F(ApplyControlDataUpdatesTest,
307 NigoriConflictPendingKeysServerEncryptEverythingCustom) {
308 Cryptographer* cryptographer;
309 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
310 KeyParams other_params = {"localhost", "dummy", "foobar"};
311 KeyParams local_params = {"localhost", "dummy", "local"};
313 syncable::ReadTransaction trans(FROM_HERE, directory());
314 cryptographer = directory()->GetCryptographer(&trans);
315 EXPECT_TRUE(encrypted_types.Equals(
316 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
319 // Set up a temporary cryptographer to generate new keys with.
320 Cryptographer other_cryptographer(cryptographer->encryptor());
321 other_cryptographer.AddKey(other_params);
323 // Create server specifics with pending keys, new encrypted types,
324 // and a custom passphrase (unmigrated).
325 sync_pb::EntitySpecifics server_specifics;
326 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
327 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
328 server_nigori->set_encrypt_everything(true);
329 server_nigori->set_keybag_is_frozen(true);
330 int64 nigori_handle =
331 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
332 server_specifics,
333 true);
335 // Initialize the local cryptographer with the local keys.
336 cryptographer->AddKey(local_params);
337 EXPECT_TRUE(cryptographer->is_ready());
339 // Set up a local nigori with the local encryption keys and default encrypted
340 // types.
341 sync_pb::EntitySpecifics local_specifics;
342 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
343 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
344 local_nigori->set_encrypt_everything(false);
345 local_nigori->set_keybag_is_frozen(true);
346 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
347 nigori_handle, local_specifics));
348 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
349 // to use.
351 syncable::ReadTransaction trans(FROM_HERE, directory());
352 cryptographer = directory()->GetCryptographer(&trans);
353 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
354 *local_nigori,
355 &trans);
358 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
359 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
360 ApplyControlDataUpdates(directory());
361 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
362 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
364 EXPECT_FALSE(cryptographer->is_ready());
365 EXPECT_TRUE(cryptographer->is_initialized());
366 EXPECT_TRUE(cryptographer->has_pending_keys());
367 EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey(
368 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
369 nigori().encryption_keybag()));
370 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
371 nigori().keybag_is_frozen());
372 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
373 nigori().encrypt_everything());
375 syncable::ReadTransaction trans(FROM_HERE, directory());
376 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
377 .Equals(ModelTypeSet::All()));
381 // Verify we handle a nigori node conflict by merging encryption keys and
382 // types, but preserve the custom passphrase state of the server.
383 // Initial sync ended should be set.
384 TEST_F(ApplyControlDataUpdatesTest,
385 NigoriConflictPendingKeysLocalEncryptEverythingCustom) {
386 Cryptographer* cryptographer;
387 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
388 KeyParams other_params = {"localhost", "dummy", "foobar"};
389 KeyParams local_params = {"localhost", "dummy", "local"};
391 syncable::ReadTransaction trans(FROM_HERE, directory());
392 cryptographer = directory()->GetCryptographer(&trans);
393 EXPECT_TRUE(encrypted_types.Equals(
394 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
397 // Set up a temporary cryptographer to generate new keys with.
398 Cryptographer other_cryptographer(cryptographer->encryptor());
399 other_cryptographer.AddKey(other_params);
401 // Create server specifics with pending keys, new encrypted types,
402 // and a custom passphrase (unmigrated).
403 sync_pb::EntitySpecifics server_specifics;
404 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
405 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
406 server_nigori->set_encrypt_everything(false);
407 server_nigori->set_keybag_is_frozen(false);
408 int64 nigori_handle =
409 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
410 server_specifics,
411 true);
413 // Initialize the local cryptographer with the local keys.
414 cryptographer->AddKey(local_params);
415 EXPECT_TRUE(cryptographer->is_ready());
417 // Set up a local nigori with the local encryption keys and default encrypted
418 // types.
419 sync_pb::EntitySpecifics local_specifics;
420 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
421 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
422 local_nigori->set_encrypt_everything(true);
423 local_nigori->set_keybag_is_frozen(true);
424 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
425 nigori_handle, local_specifics));
426 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
427 // to use.
429 syncable::ReadTransaction trans(FROM_HERE, directory());
430 cryptographer = directory()->GetCryptographer(&trans);
431 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
432 *local_nigori,
433 &trans);
436 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
437 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
438 ApplyControlDataUpdates(directory());
439 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
440 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
442 EXPECT_FALSE(cryptographer->is_ready());
443 EXPECT_TRUE(cryptographer->is_initialized());
444 EXPECT_TRUE(cryptographer->has_pending_keys());
445 EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey(
446 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
447 nigori().encryption_keybag()));
448 EXPECT_FALSE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
449 nigori().keybag_is_frozen());
450 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
451 nigori().encrypt_everything());
453 syncable::ReadTransaction trans(FROM_HERE, directory());
454 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
455 .Equals(ModelTypeSet::All()));
459 // If the conflicting nigori has a subset of the local keys, the conflict
460 // resolution should preserve the full local keys. Initial sync ended should be
461 // set.
462 TEST_F(ApplyControlDataUpdatesTest,
463 NigoriConflictOldKeys) {
464 Cryptographer* cryptographer;
465 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
466 KeyParams old_params = {"localhost", "dummy", "old"};
467 KeyParams new_params = {"localhost", "dummy", "new"};
469 syncable::ReadTransaction trans(FROM_HERE, directory());
470 cryptographer = directory()->GetCryptographer(&trans);
471 EXPECT_TRUE(encrypted_types.Equals(
472 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
475 // Set up the cryptographer with old keys
476 cryptographer->AddKey(old_params);
478 // Create server specifics with old keys and new encrypted types.
479 sync_pb::EntitySpecifics server_specifics;
480 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
481 cryptographer->GetKeys(server_nigori->mutable_encryption_keybag());
482 server_nigori->set_encrypt_everything(true);
483 int64 nigori_handle =
484 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
485 server_specifics,
486 true);
488 // Add the new keys to the cryptogrpaher
489 cryptographer->AddKey(new_params);
490 EXPECT_TRUE(cryptographer->is_ready());
492 // Set up a local nigori with the superset of keys.
493 sync_pb::EntitySpecifics local_specifics;
494 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
495 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
496 local_nigori->set_encrypt_everything(false);
497 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
498 nigori_handle, local_specifics));
499 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
500 // to use.
502 syncable::ReadTransaction trans(FROM_HERE, directory());
503 cryptographer = directory()->GetCryptographer(&trans);
504 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
505 *local_nigori,
506 &trans);
509 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
510 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
511 ApplyControlDataUpdates(directory());
512 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
513 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
515 EXPECT_TRUE(cryptographer->is_ready());
516 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
517 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
518 nigori().encryption_keybag()));
519 EXPECT_FALSE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
520 nigori().keybag_is_frozen());
521 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
522 nigori().encrypt_everything());
524 syncable::ReadTransaction trans(FROM_HERE, directory());
525 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
526 .Equals(ModelTypeSet::All()));
530 // If both nigoris are migrated, but we also set a custom passphrase locally,
531 // the local nigori should be preserved.
532 TEST_F(ApplyControlDataUpdatesTest,
533 NigoriConflictBothMigratedLocalCustom) {
534 Cryptographer* cryptographer;
535 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
536 KeyParams old_params = {"localhost", "dummy", "old"};
537 KeyParams new_params = {"localhost", "dummy", "new"};
539 syncable::ReadTransaction trans(FROM_HERE, directory());
540 cryptographer = directory()->GetCryptographer(&trans);
541 EXPECT_TRUE(encrypted_types.Equals(
542 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
545 // Set up the cryptographer with new keys
546 Cryptographer other_cryptographer(cryptographer->encryptor());
547 other_cryptographer.AddKey(old_params);
549 // Create server specifics with a migrated keystore passphrase type.
550 sync_pb::EntitySpecifics server_specifics;
551 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
552 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
553 server_nigori->set_encrypt_everything(false);
554 server_nigori->set_keybag_is_frozen(true);
555 server_nigori->set_passphrase_type(
556 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
557 server_nigori->mutable_keystore_decryptor_token();
558 int64 nigori_handle =
559 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
560 server_specifics,
561 true);
563 // Add the new keys to the cryptographer.
564 cryptographer->AddKey(old_params);
565 cryptographer->AddKey(new_params);
566 EXPECT_TRUE(cryptographer->is_ready());
568 // Set up a local nigori with a migrated custom passphrase type
569 sync_pb::EntitySpecifics local_specifics;
570 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
571 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
572 local_nigori->set_encrypt_everything(true);
573 local_nigori->set_keybag_is_frozen(true);
574 local_nigori->set_passphrase_type(
575 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
576 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
577 nigori_handle, local_specifics));
578 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
579 // to use.
581 syncable::ReadTransaction trans(FROM_HERE, directory());
582 cryptographer = directory()->GetCryptographer(&trans);
583 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
584 *local_nigori,
585 &trans);
588 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
589 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
590 ApplyControlDataUpdates(directory());
591 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
592 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
594 EXPECT_TRUE(cryptographer->is_ready());
595 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
596 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
597 nigori().encryption_keybag()));
598 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
599 nigori().keybag_is_frozen());
600 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
601 nigori().encrypt_everything());
602 EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
603 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
604 nigori().passphrase_type());
606 syncable::ReadTransaction trans(FROM_HERE, directory());
607 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
608 .Equals(ModelTypeSet::All()));
612 // If both nigoris are migrated, but a custom passphrase with a new key was
613 // set remotely, the remote nigori should be preserved.
614 TEST_F(ApplyControlDataUpdatesTest,
615 NigoriConflictBothMigratedServerCustom) {
616 Cryptographer* cryptographer;
617 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
618 KeyParams old_params = {"localhost", "dummy", "old"};
619 KeyParams new_params = {"localhost", "dummy", "new"};
621 syncable::ReadTransaction trans(FROM_HERE, directory());
622 cryptographer = directory()->GetCryptographer(&trans);
623 EXPECT_TRUE(encrypted_types.Equals(
624 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
627 // Set up the cryptographer with both new keys and old keys.
628 Cryptographer other_cryptographer(cryptographer->encryptor());
629 other_cryptographer.AddKey(old_params);
630 other_cryptographer.AddKey(new_params);
632 // Create server specifics with a migrated custom passphrase type.
633 sync_pb::EntitySpecifics server_specifics;
634 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
635 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
636 server_nigori->set_encrypt_everything(true);
637 server_nigori->set_keybag_is_frozen(true);
638 server_nigori->set_passphrase_type(
639 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
640 int64 nigori_handle =
641 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
642 server_specifics,
643 true);
645 // Add the old keys to the cryptographer.
646 cryptographer->AddKey(old_params);
647 EXPECT_TRUE(cryptographer->is_ready());
649 // Set up a local nigori with a migrated keystore passphrase type
650 sync_pb::EntitySpecifics local_specifics;
651 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
652 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
653 local_nigori->set_encrypt_everything(false);
654 local_nigori->set_keybag_is_frozen(true);
655 local_nigori->set_passphrase_type(
656 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
657 server_nigori->mutable_keystore_decryptor_token();
658 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
659 nigori_handle, local_specifics));
660 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
661 // to use.
663 syncable::ReadTransaction trans(FROM_HERE, directory());
664 cryptographer = directory()->GetCryptographer(&trans);
665 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
666 *local_nigori,
667 &trans);
670 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
671 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
672 ApplyControlDataUpdates(directory());
673 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
674 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
676 EXPECT_TRUE(cryptographer->is_initialized());
677 EXPECT_TRUE(cryptographer->has_pending_keys());
678 EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey(
679 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
680 nigori().encryption_keybag()));
681 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
682 nigori().keybag_is_frozen());
683 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
684 nigori().encrypt_everything());
685 EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
686 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
687 nigori().passphrase_type());
689 syncable::ReadTransaction trans(FROM_HERE, directory());
690 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
691 .Equals(ModelTypeSet::All()));
695 // If the local nigori is migrated but the server is not, preserve the local
696 // nigori.
697 TEST_F(ApplyControlDataUpdatesTest,
698 NigoriConflictLocalMigrated) {
699 Cryptographer* cryptographer;
700 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
701 KeyParams old_params = {"localhost", "dummy", "old"};
702 KeyParams new_params = {"localhost", "dummy", "new"};
704 syncable::ReadTransaction trans(FROM_HERE, directory());
705 cryptographer = directory()->GetCryptographer(&trans);
706 EXPECT_TRUE(encrypted_types.Equals(
707 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
710 // Set up the cryptographer with both new keys and old keys.
711 Cryptographer other_cryptographer(cryptographer->encryptor());
712 other_cryptographer.AddKey(old_params);
714 // Create server specifics with an unmigrated implicit passphrase type.
715 sync_pb::EntitySpecifics server_specifics;
716 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
717 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
718 server_nigori->set_encrypt_everything(true);
719 server_nigori->set_keybag_is_frozen(false);
720 int64 nigori_handle =
721 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
722 server_specifics,
723 true);
725 // Add the old keys to the cryptographer.
726 cryptographer->AddKey(old_params);
727 cryptographer->AddKey(new_params);
728 EXPECT_TRUE(cryptographer->is_ready());
730 // Set up a local nigori with a migrated custom passphrase type
731 sync_pb::EntitySpecifics local_specifics;
732 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
733 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
734 local_nigori->set_encrypt_everything(true);
735 local_nigori->set_keybag_is_frozen(true);
736 local_nigori->set_passphrase_type(
737 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
738 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
739 nigori_handle, local_specifics));
740 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
741 // to use.
743 syncable::ReadTransaction trans(FROM_HERE, directory());
744 cryptographer = directory()->GetCryptographer(&trans);
745 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
746 *local_nigori,
747 &trans);
750 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
751 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
752 ApplyControlDataUpdates(directory());
753 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
754 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
756 EXPECT_TRUE(cryptographer->is_ready());
757 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
758 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
759 nigori().encryption_keybag()));
760 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
761 nigori().keybag_is_frozen());
762 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
763 nigori().encrypt_everything());
764 EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
765 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
766 nigori().passphrase_type());
768 syncable::ReadTransaction trans(FROM_HERE, directory());
769 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
770 .Equals(ModelTypeSet::All()));
774 // If the server nigori is migrated but the local is not, preserve the server
775 // nigori.
776 TEST_F(ApplyControlDataUpdatesTest,
777 NigoriConflictServerMigrated) {
778 Cryptographer* cryptographer;
779 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
780 KeyParams old_params = {"localhost", "dummy", "old"};
781 KeyParams new_params = {"localhost", "dummy", "new"};
783 syncable::ReadTransaction trans(FROM_HERE, directory());
784 cryptographer = directory()->GetCryptographer(&trans);
785 EXPECT_TRUE(encrypted_types.Equals(
786 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
789 // Set up the cryptographer with both new keys and old keys.
790 Cryptographer other_cryptographer(cryptographer->encryptor());
791 other_cryptographer.AddKey(old_params);
793 // Create server specifics with an migrated keystore passphrase type.
794 sync_pb::EntitySpecifics server_specifics;
795 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
796 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
797 server_nigori->set_encrypt_everything(false);
798 server_nigori->set_keybag_is_frozen(true);
799 server_nigori->set_passphrase_type(
800 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
801 server_nigori->mutable_keystore_decryptor_token();
802 int64 nigori_handle =
803 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
804 server_specifics,
805 true);
807 // Add the old keys to the cryptographer.
808 cryptographer->AddKey(old_params);
809 cryptographer->AddKey(new_params);
810 EXPECT_TRUE(cryptographer->is_ready());
812 // Set up a local nigori with a migrated custom passphrase type
813 sync_pb::EntitySpecifics local_specifics;
814 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
815 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
816 local_nigori->set_encrypt_everything(false);
817 local_nigori->set_keybag_is_frozen(false);
818 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
819 nigori_handle, local_specifics));
820 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
821 // to use.
823 syncable::ReadTransaction trans(FROM_HERE, directory());
824 cryptographer = directory()->GetCryptographer(&trans);
825 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
826 *local_nigori,
827 &trans);
830 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
831 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
832 ApplyControlDataUpdates(directory());
833 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
834 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
836 EXPECT_TRUE(cryptographer->is_ready());
837 // Note: we didn't overwrite the encryption keybag with the local keys. The
838 // sync encryption handler will do that when it detects that the new
839 // keybag is out of date (and update the keystore bootstrap if necessary).
840 EXPECT_FALSE(cryptographer->CanDecryptUsingDefaultKey(
841 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
842 nigori().encryption_keybag()));
843 EXPECT_TRUE(cryptographer->CanDecrypt(
844 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
845 nigori().encryption_keybag()));
846 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
847 nigori().keybag_is_frozen());
848 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
849 nigori().has_keystore_decryptor_token());
850 EXPECT_EQ(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE,
851 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
852 nigori().passphrase_type());
854 syncable::ReadTransaction trans(FROM_HERE, directory());
858 // Check that we can apply a simple control datatype node successfully.
859 TEST_F(ApplyControlDataUpdatesTest, ControlApply) {
860 std::string experiment_id = "experiment";
861 sync_pb::EntitySpecifics specifics;
862 specifics.mutable_experiments()->mutable_keystore_encryption()->
863 set_enabled(true);
864 int64 experiment_handle = entry_factory_->CreateUnappliedNewItem(
865 experiment_id, specifics, false);
866 ApplyControlDataUpdates(directory());
868 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(experiment_handle));
869 EXPECT_TRUE(
870 entry_factory_->GetLocalSpecificsForItem(experiment_handle).
871 experiments().keystore_encryption().enabled());
874 // Verify that we apply top level folders before their children.
875 TEST_F(ApplyControlDataUpdatesTest, ControlApplyParentBeforeChild) {
876 std::string parent_id = "parent";
877 std::string experiment_id = "experiment";
878 sync_pb::EntitySpecifics specifics;
879 specifics.mutable_experiments()->mutable_keystore_encryption()->
880 set_enabled(true);
881 int64 experiment_handle = entry_factory_->CreateUnappliedNewItemWithParent(
882 experiment_id, specifics, parent_id);
883 int64 parent_handle = entry_factory_->CreateUnappliedNewItem(
884 parent_id, specifics, true);
885 ApplyControlDataUpdates(directory());
887 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(parent_handle));
888 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(experiment_handle));
889 EXPECT_TRUE(
890 entry_factory_->GetLocalSpecificsForItem(experiment_handle).
891 experiments().keystore_encryption().enabled());
894 // Verify that we handle control datatype conflicts by preserving the server
895 // data.
896 TEST_F(ApplyControlDataUpdatesTest, ControlConflict) {
897 std::string experiment_id = "experiment";
898 sync_pb::EntitySpecifics local_specifics, server_specifics;
899 server_specifics.mutable_experiments()->mutable_keystore_encryption()->
900 set_enabled(true);
901 local_specifics.mutable_experiments()->mutable_keystore_encryption()->
902 set_enabled(false);
903 int64 experiment_handle = entry_factory_->CreateSyncedItem(
904 experiment_id, EXPERIMENTS, false);
905 entry_factory_->SetServerSpecificsForItem(experiment_handle,
906 server_specifics);
907 entry_factory_->SetLocalSpecificsForItem(experiment_handle,
908 local_specifics);
909 ApplyControlDataUpdates(directory());
911 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(experiment_handle));
912 EXPECT_TRUE(
913 entry_factory_->GetLocalSpecificsForItem(experiment_handle).
914 experiments().keystore_encryption().enabled());
917 } // namespace syncer