Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / sync / engine / apply_control_data_updates_unittest.cc
blob7248d141815c36c8d7baab23904141715d98b7c7
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 virtual ~ApplyControlDataUpdatesTest() {}
40 virtual void SetUp() {
41 dir_maker_.SetUp();
42 entry_factory_.reset(new TestEntryFactory(directory()));
45 virtual void TearDown() {
46 dir_maker_.TearDown();
49 syncable::Directory* directory() {
50 return dir_maker_.directory();
53 TestIdFactory id_factory_;
54 scoped_ptr<TestEntryFactory> entry_factory_;
55 private:
56 base::MessageLoop loop_; // Needed for directory init.
57 TestDirectorySetterUpper dir_maker_;
59 DISALLOW_COPY_AND_ASSIGN(ApplyControlDataUpdatesTest);
62 // Verify that applying a nigori node sets initial sync ended properly,
63 // updates the set of encrypted types, and updates the cryptographer.
64 TEST_F(ApplyControlDataUpdatesTest, NigoriUpdate) {
65 // Storing the cryptographer separately is bad, but for this test we
66 // know it's safe.
67 Cryptographer* cryptographer;
68 ModelTypeSet encrypted_types;
69 encrypted_types.PutAll(SyncEncryptionHandler::SensitiveTypes());
72 syncable::ReadTransaction trans(FROM_HERE, directory());
73 cryptographer = directory()->GetCryptographer(&trans);
74 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
75 .Equals(encrypted_types));
78 // Nigori node updates should update the Cryptographer.
79 Cryptographer other_cryptographer(cryptographer->encryptor());
80 KeyParams params = {"localhost", "dummy", "foobar"};
81 other_cryptographer.AddKey(params);
83 sync_pb::EntitySpecifics specifics;
84 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
85 other_cryptographer.GetKeys(nigori->mutable_encryption_keybag());
86 nigori->set_encrypt_everything(true);
87 entry_factory_->CreateUnappliedNewItem(
88 ModelTypeToRootTag(NIGORI), specifics, true);
89 EXPECT_FALSE(cryptographer->has_pending_keys());
91 ApplyControlDataUpdates(directory());
93 EXPECT_FALSE(cryptographer->is_ready());
94 EXPECT_TRUE(cryptographer->has_pending_keys());
96 syncable::ReadTransaction trans(FROM_HERE, directory());
97 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
98 .Equals(ModelTypeSet::All()));
102 // Create some local unsynced and unencrypted data. Apply a nigori update that
103 // turns on encryption for the unsynced data. Ensure we properly encrypt the
104 // data as part of the nigori update. Apply another nigori update with no
105 // changes. Ensure we ignore already-encrypted unsynced data and that nothing
106 // breaks.
107 TEST_F(ApplyControlDataUpdatesTest, EncryptUnsyncedChanges) {
108 // Storing the cryptographer separately is bad, but for this test we
109 // know it's safe.
110 Cryptographer* cryptographer;
111 ModelTypeSet encrypted_types;
112 encrypted_types.PutAll(SyncEncryptionHandler::SensitiveTypes());
114 syncable::ReadTransaction trans(FROM_HERE, directory());
115 cryptographer = directory()->GetCryptographer(&trans);
116 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
117 .Equals(encrypted_types));
119 // With default encrypted_types, this should be true.
120 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
122 Syncer::UnsyncedMetaHandles handles;
123 GetUnsyncedEntries(&trans, &handles);
124 EXPECT_TRUE(handles.empty());
127 // Create unsynced bookmarks without encryption.
128 // First item is a folder
129 Id folder_id = id_factory_.NewLocalId();
130 entry_factory_->CreateUnsyncedItem(folder_id, id_factory_.root(), "folder",
131 true, BOOKMARKS, NULL);
132 // Next five items are children of the folder
133 size_t i;
134 size_t batch_s = 5;
135 for (i = 0; i < batch_s; ++i) {
136 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
137 base::StringPrintf("Item %" PRIuS "", i),
138 false, BOOKMARKS, NULL);
140 // Next five items are children of the root.
141 for (; i < 2*batch_s; ++i) {
142 entry_factory_->CreateUnsyncedItem(
143 id_factory_.NewLocalId(), id_factory_.root(),
144 base::StringPrintf("Item %" PRIuS "", i), false,
145 BOOKMARKS, NULL);
148 KeyParams params = {"localhost", "dummy", "foobar"};
149 cryptographer->AddKey(params);
150 sync_pb::EntitySpecifics specifics;
151 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
152 cryptographer->GetKeys(nigori->mutable_encryption_keybag());
153 nigori->set_encrypt_everything(true);
154 encrypted_types.Put(BOOKMARKS);
155 entry_factory_->CreateUnappliedNewItem(
156 ModelTypeToRootTag(NIGORI), specifics, true);
157 EXPECT_FALSE(cryptographer->has_pending_keys());
158 EXPECT_TRUE(cryptographer->is_ready());
161 // Ensure we have unsynced nodes that aren't properly encrypted.
162 syncable::ReadTransaction trans(FROM_HERE, directory());
163 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
165 Syncer::UnsyncedMetaHandles handles;
166 GetUnsyncedEntries(&trans, &handles);
167 EXPECT_EQ(2*batch_s+1, handles.size());
170 ApplyControlDataUpdates(directory());
172 EXPECT_FALSE(cryptographer->has_pending_keys());
173 EXPECT_TRUE(cryptographer->is_ready());
175 syncable::ReadTransaction trans(FROM_HERE, directory());
177 // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes
178 // should be encrypted now.
179 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
180 .Equals(ModelTypeSet::All()));
181 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
183 Syncer::UnsyncedMetaHandles handles;
184 GetUnsyncedEntries(&trans, &handles);
185 EXPECT_EQ(2*batch_s+1, handles.size());
188 // Simulate another nigori update that doesn't change anything.
190 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory());
191 MutableEntry entry(&trans, syncable::GET_TYPE_ROOT, NIGORI);
192 ASSERT_TRUE(entry.good());
193 entry.PutServerVersion(entry_factory_->GetNextRevision());
194 entry.PutIsUnappliedUpdate(true);
197 ApplyControlDataUpdates(directory());
199 EXPECT_FALSE(cryptographer->has_pending_keys());
200 EXPECT_TRUE(cryptographer->is_ready());
202 syncable::ReadTransaction trans(FROM_HERE, directory());
204 // All our changes should still be encrypted.
205 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
206 .Equals(ModelTypeSet::All()));
207 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
209 Syncer::UnsyncedMetaHandles handles;
210 GetUnsyncedEntries(&trans, &handles);
211 EXPECT_EQ(2*batch_s+1, handles.size());
215 // Create some local unsynced and unencrypted changes. Receive a new nigori
216 // node enabling their encryption but also introducing pending keys. Ensure
217 // we apply the update properly without encrypting the unsynced changes or
218 // breaking.
219 TEST_F(ApplyControlDataUpdatesTest, CannotEncryptUnsyncedChanges) {
220 // Storing the cryptographer separately is bad, but for this test we
221 // know it's safe.
222 Cryptographer* cryptographer;
223 ModelTypeSet encrypted_types;
224 encrypted_types.PutAll(SyncEncryptionHandler::SensitiveTypes());
226 syncable::ReadTransaction trans(FROM_HERE, directory());
227 cryptographer = directory()->GetCryptographer(&trans);
228 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
229 .Equals(encrypted_types));
231 // With default encrypted_types, this should be true.
232 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
234 Syncer::UnsyncedMetaHandles handles;
235 GetUnsyncedEntries(&trans, &handles);
236 EXPECT_TRUE(handles.empty());
239 // Create unsynced bookmarks without encryption.
240 // First item is a folder
241 Id folder_id = id_factory_.NewLocalId();
242 entry_factory_->CreateUnsyncedItem(
243 folder_id, id_factory_.root(), "folder", true,
244 BOOKMARKS, NULL);
245 // Next five items are children of the folder
246 size_t i;
247 size_t batch_s = 5;
248 for (i = 0; i < batch_s; ++i) {
249 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
250 base::StringPrintf("Item %" PRIuS "", i),
251 false, BOOKMARKS, NULL);
253 // Next five items are children of the root.
254 for (; i < 2*batch_s; ++i) {
255 entry_factory_->CreateUnsyncedItem(
256 id_factory_.NewLocalId(), id_factory_.root(),
257 base::StringPrintf("Item %" PRIuS "", i), false,
258 BOOKMARKS, NULL);
261 // We encrypt with new keys, triggering the local cryptographer to be unready
262 // and unable to decrypt data (once updated).
263 Cryptographer other_cryptographer(cryptographer->encryptor());
264 KeyParams params = {"localhost", "dummy", "foobar"};
265 other_cryptographer.AddKey(params);
266 sync_pb::EntitySpecifics specifics;
267 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
268 other_cryptographer.GetKeys(nigori->mutable_encryption_keybag());
269 nigori->set_encrypt_everything(true);
270 encrypted_types.Put(BOOKMARKS);
271 entry_factory_->CreateUnappliedNewItem(
272 ModelTypeToRootTag(NIGORI), specifics, true);
273 EXPECT_FALSE(cryptographer->has_pending_keys());
276 // Ensure we have unsynced nodes that aren't properly encrypted.
277 syncable::ReadTransaction trans(FROM_HERE, directory());
278 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
279 Syncer::UnsyncedMetaHandles handles;
280 GetUnsyncedEntries(&trans, &handles);
281 EXPECT_EQ(2*batch_s+1, handles.size());
284 ApplyControlDataUpdates(directory());
286 EXPECT_FALSE(cryptographer->is_ready());
287 EXPECT_TRUE(cryptographer->has_pending_keys());
289 syncable::ReadTransaction trans(FROM_HERE, directory());
291 // Since we have pending keys, we would have failed to encrypt, but the
292 // cryptographer should be updated.
293 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
294 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
295 .Equals(ModelTypeSet::All()));
296 EXPECT_FALSE(cryptographer->is_ready());
297 EXPECT_TRUE(cryptographer->has_pending_keys());
299 Syncer::UnsyncedMetaHandles handles;
300 GetUnsyncedEntries(&trans, &handles);
301 EXPECT_EQ(2*batch_s+1, handles.size());
305 // Verify we handle a nigori node conflict by merging encryption keys and
306 // types, but preserve the custom passphrase state of the server.
307 // Initial sync ended should be set.
308 TEST_F(ApplyControlDataUpdatesTest,
309 NigoriConflictPendingKeysServerEncryptEverythingCustom) {
310 Cryptographer* cryptographer;
311 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
312 KeyParams other_params = {"localhost", "dummy", "foobar"};
313 KeyParams local_params = {"localhost", "dummy", "local"};
315 syncable::ReadTransaction trans(FROM_HERE, directory());
316 cryptographer = directory()->GetCryptographer(&trans);
317 EXPECT_TRUE(encrypted_types.Equals(
318 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
321 // Set up a temporary cryptographer to generate new keys with.
322 Cryptographer other_cryptographer(cryptographer->encryptor());
323 other_cryptographer.AddKey(other_params);
325 // Create server specifics with pending keys, new encrypted types,
326 // and a custom passphrase (unmigrated).
327 sync_pb::EntitySpecifics server_specifics;
328 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
329 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
330 server_nigori->set_encrypt_everything(true);
331 server_nigori->set_keybag_is_frozen(true);
332 int64 nigori_handle =
333 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
334 server_specifics,
335 true);
337 // Initialize the local cryptographer with the local keys.
338 cryptographer->AddKey(local_params);
339 EXPECT_TRUE(cryptographer->is_ready());
341 // Set up a local nigori with the local encryption keys and default encrypted
342 // types.
343 sync_pb::EntitySpecifics local_specifics;
344 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
345 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
346 local_nigori->set_encrypt_everything(false);
347 local_nigori->set_keybag_is_frozen(true);
348 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
349 nigori_handle, local_specifics));
350 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
351 // to use.
353 syncable::ReadTransaction trans(FROM_HERE, directory());
354 cryptographer = directory()->GetCryptographer(&trans);
355 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
356 *local_nigori,
357 &trans);
360 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
361 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
362 ApplyControlDataUpdates(directory());
363 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
364 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
366 EXPECT_FALSE(cryptographer->is_ready());
367 EXPECT_TRUE(cryptographer->is_initialized());
368 EXPECT_TRUE(cryptographer->has_pending_keys());
369 EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey(
370 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
371 nigori().encryption_keybag()));
372 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
373 nigori().keybag_is_frozen());
374 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
375 nigori().encrypt_everything());
377 syncable::ReadTransaction trans(FROM_HERE, directory());
378 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
379 .Equals(ModelTypeSet::All()));
383 // Verify we handle a nigori node conflict by merging encryption keys and
384 // types, but preserve the custom passphrase state of the server.
385 // Initial sync ended should be set.
386 TEST_F(ApplyControlDataUpdatesTest,
387 NigoriConflictPendingKeysLocalEncryptEverythingCustom) {
388 Cryptographer* cryptographer;
389 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
390 KeyParams other_params = {"localhost", "dummy", "foobar"};
391 KeyParams local_params = {"localhost", "dummy", "local"};
393 syncable::ReadTransaction trans(FROM_HERE, directory());
394 cryptographer = directory()->GetCryptographer(&trans);
395 EXPECT_TRUE(encrypted_types.Equals(
396 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
399 // Set up a temporary cryptographer to generate new keys with.
400 Cryptographer other_cryptographer(cryptographer->encryptor());
401 other_cryptographer.AddKey(other_params);
403 // Create server specifics with pending keys, new encrypted types,
404 // and a custom passphrase (unmigrated).
405 sync_pb::EntitySpecifics server_specifics;
406 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
407 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
408 server_nigori->set_encrypt_everything(false);
409 server_nigori->set_keybag_is_frozen(false);
410 int64 nigori_handle =
411 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
412 server_specifics,
413 true);
415 // Initialize the local cryptographer with the local keys.
416 cryptographer->AddKey(local_params);
417 EXPECT_TRUE(cryptographer->is_ready());
419 // Set up a local nigori with the local encryption keys and default encrypted
420 // types.
421 sync_pb::EntitySpecifics local_specifics;
422 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
423 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
424 local_nigori->set_encrypt_everything(true);
425 local_nigori->set_keybag_is_frozen(true);
426 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
427 nigori_handle, local_specifics));
428 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
429 // to use.
431 syncable::ReadTransaction trans(FROM_HERE, directory());
432 cryptographer = directory()->GetCryptographer(&trans);
433 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
434 *local_nigori,
435 &trans);
438 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
439 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
440 ApplyControlDataUpdates(directory());
441 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
442 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
444 EXPECT_FALSE(cryptographer->is_ready());
445 EXPECT_TRUE(cryptographer->is_initialized());
446 EXPECT_TRUE(cryptographer->has_pending_keys());
447 EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey(
448 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
449 nigori().encryption_keybag()));
450 EXPECT_FALSE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
451 nigori().keybag_is_frozen());
452 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
453 nigori().encrypt_everything());
455 syncable::ReadTransaction trans(FROM_HERE, directory());
456 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
457 .Equals(ModelTypeSet::All()));
461 // If the conflicting nigori has a subset of the local keys, the conflict
462 // resolution should preserve the full local keys. Initial sync ended should be
463 // set.
464 TEST_F(ApplyControlDataUpdatesTest,
465 NigoriConflictOldKeys) {
466 Cryptographer* cryptographer;
467 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
468 KeyParams old_params = {"localhost", "dummy", "old"};
469 KeyParams new_params = {"localhost", "dummy", "new"};
471 syncable::ReadTransaction trans(FROM_HERE, directory());
472 cryptographer = directory()->GetCryptographer(&trans);
473 EXPECT_TRUE(encrypted_types.Equals(
474 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
477 // Set up the cryptographer with old keys
478 cryptographer->AddKey(old_params);
480 // Create server specifics with old keys and new encrypted types.
481 sync_pb::EntitySpecifics server_specifics;
482 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
483 cryptographer->GetKeys(server_nigori->mutable_encryption_keybag());
484 server_nigori->set_encrypt_everything(true);
485 int64 nigori_handle =
486 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
487 server_specifics,
488 true);
490 // Add the new keys to the cryptogrpaher
491 cryptographer->AddKey(new_params);
492 EXPECT_TRUE(cryptographer->is_ready());
494 // Set up a local nigori with the superset of keys.
495 sync_pb::EntitySpecifics local_specifics;
496 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
497 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
498 local_nigori->set_encrypt_everything(false);
499 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
500 nigori_handle, local_specifics));
501 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
502 // to use.
504 syncable::ReadTransaction trans(FROM_HERE, directory());
505 cryptographer = directory()->GetCryptographer(&trans);
506 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
507 *local_nigori,
508 &trans);
511 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
512 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
513 ApplyControlDataUpdates(directory());
514 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
515 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
517 EXPECT_TRUE(cryptographer->is_ready());
518 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
519 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
520 nigori().encryption_keybag()));
521 EXPECT_FALSE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
522 nigori().keybag_is_frozen());
523 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
524 nigori().encrypt_everything());
526 syncable::ReadTransaction trans(FROM_HERE, directory());
527 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
528 .Equals(ModelTypeSet::All()));
532 // If both nigoris are migrated, but we also set a custom passphrase locally,
533 // the local nigori should be preserved.
534 TEST_F(ApplyControlDataUpdatesTest,
535 NigoriConflictBothMigratedLocalCustom) {
536 Cryptographer* cryptographer;
537 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
538 KeyParams old_params = {"localhost", "dummy", "old"};
539 KeyParams new_params = {"localhost", "dummy", "new"};
541 syncable::ReadTransaction trans(FROM_HERE, directory());
542 cryptographer = directory()->GetCryptographer(&trans);
543 EXPECT_TRUE(encrypted_types.Equals(
544 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
547 // Set up the cryptographer with new keys
548 Cryptographer other_cryptographer(cryptographer->encryptor());
549 other_cryptographer.AddKey(old_params);
551 // Create server specifics with a migrated keystore passphrase type.
552 sync_pb::EntitySpecifics server_specifics;
553 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
554 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
555 server_nigori->set_encrypt_everything(false);
556 server_nigori->set_keybag_is_frozen(true);
557 server_nigori->set_passphrase_type(
558 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
559 server_nigori->mutable_keystore_decryptor_token();
560 int64 nigori_handle =
561 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
562 server_specifics,
563 true);
565 // Add the new keys to the cryptographer.
566 cryptographer->AddKey(old_params);
567 cryptographer->AddKey(new_params);
568 EXPECT_TRUE(cryptographer->is_ready());
570 // Set up a local nigori with a migrated custom passphrase type
571 sync_pb::EntitySpecifics local_specifics;
572 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
573 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
574 local_nigori->set_encrypt_everything(true);
575 local_nigori->set_keybag_is_frozen(true);
576 local_nigori->set_passphrase_type(
577 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
578 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
579 nigori_handle, local_specifics));
580 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
581 // to use.
583 syncable::ReadTransaction trans(FROM_HERE, directory());
584 cryptographer = directory()->GetCryptographer(&trans);
585 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
586 *local_nigori,
587 &trans);
590 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
591 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
592 ApplyControlDataUpdates(directory());
593 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
594 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
596 EXPECT_TRUE(cryptographer->is_ready());
597 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
598 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
599 nigori().encryption_keybag()));
600 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
601 nigori().keybag_is_frozen());
602 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
603 nigori().encrypt_everything());
604 EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
605 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
606 nigori().passphrase_type());
608 syncable::ReadTransaction trans(FROM_HERE, directory());
609 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
610 .Equals(ModelTypeSet::All()));
614 // If both nigoris are migrated, but a custom passphrase with a new key was
615 // set remotely, the remote nigori should be preserved.
616 TEST_F(ApplyControlDataUpdatesTest,
617 NigoriConflictBothMigratedServerCustom) {
618 Cryptographer* cryptographer;
619 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
620 KeyParams old_params = {"localhost", "dummy", "old"};
621 KeyParams new_params = {"localhost", "dummy", "new"};
623 syncable::ReadTransaction trans(FROM_HERE, directory());
624 cryptographer = directory()->GetCryptographer(&trans);
625 EXPECT_TRUE(encrypted_types.Equals(
626 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
629 // Set up the cryptographer with both new keys and old keys.
630 Cryptographer other_cryptographer(cryptographer->encryptor());
631 other_cryptographer.AddKey(old_params);
632 other_cryptographer.AddKey(new_params);
634 // Create server specifics with a migrated custom passphrase type.
635 sync_pb::EntitySpecifics server_specifics;
636 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
637 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
638 server_nigori->set_encrypt_everything(true);
639 server_nigori->set_keybag_is_frozen(true);
640 server_nigori->set_passphrase_type(
641 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
642 int64 nigori_handle =
643 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
644 server_specifics,
645 true);
647 // Add the old keys to the cryptographer.
648 cryptographer->AddKey(old_params);
649 EXPECT_TRUE(cryptographer->is_ready());
651 // Set up a local nigori with a migrated keystore passphrase type
652 sync_pb::EntitySpecifics local_specifics;
653 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
654 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
655 local_nigori->set_encrypt_everything(false);
656 local_nigori->set_keybag_is_frozen(true);
657 local_nigori->set_passphrase_type(
658 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
659 server_nigori->mutable_keystore_decryptor_token();
660 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
661 nigori_handle, local_specifics));
662 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
663 // to use.
665 syncable::ReadTransaction trans(FROM_HERE, directory());
666 cryptographer = directory()->GetCryptographer(&trans);
667 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
668 *local_nigori,
669 &trans);
672 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
673 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
674 ApplyControlDataUpdates(directory());
675 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
676 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
678 EXPECT_TRUE(cryptographer->is_initialized());
679 EXPECT_TRUE(cryptographer->has_pending_keys());
680 EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey(
681 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
682 nigori().encryption_keybag()));
683 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
684 nigori().keybag_is_frozen());
685 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
686 nigori().encrypt_everything());
687 EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
688 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
689 nigori().passphrase_type());
691 syncable::ReadTransaction trans(FROM_HERE, directory());
692 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
693 .Equals(ModelTypeSet::All()));
697 // If the local nigori is migrated but the server is not, preserve the local
698 // nigori.
699 TEST_F(ApplyControlDataUpdatesTest,
700 NigoriConflictLocalMigrated) {
701 Cryptographer* cryptographer;
702 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
703 KeyParams old_params = {"localhost", "dummy", "old"};
704 KeyParams new_params = {"localhost", "dummy", "new"};
706 syncable::ReadTransaction trans(FROM_HERE, directory());
707 cryptographer = directory()->GetCryptographer(&trans);
708 EXPECT_TRUE(encrypted_types.Equals(
709 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
712 // Set up the cryptographer with both new keys and old keys.
713 Cryptographer other_cryptographer(cryptographer->encryptor());
714 other_cryptographer.AddKey(old_params);
716 // Create server specifics with an unmigrated implicit passphrase type.
717 sync_pb::EntitySpecifics server_specifics;
718 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
719 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
720 server_nigori->set_encrypt_everything(true);
721 server_nigori->set_keybag_is_frozen(false);
722 int64 nigori_handle =
723 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
724 server_specifics,
725 true);
727 // Add the old keys to the cryptographer.
728 cryptographer->AddKey(old_params);
729 cryptographer->AddKey(new_params);
730 EXPECT_TRUE(cryptographer->is_ready());
732 // Set up a local nigori with a migrated custom passphrase type
733 sync_pb::EntitySpecifics local_specifics;
734 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
735 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
736 local_nigori->set_encrypt_everything(true);
737 local_nigori->set_keybag_is_frozen(true);
738 local_nigori->set_passphrase_type(
739 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
740 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
741 nigori_handle, local_specifics));
742 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
743 // to use.
745 syncable::ReadTransaction trans(FROM_HERE, directory());
746 cryptographer = directory()->GetCryptographer(&trans);
747 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
748 *local_nigori,
749 &trans);
752 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
753 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
754 ApplyControlDataUpdates(directory());
755 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
756 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
758 EXPECT_TRUE(cryptographer->is_ready());
759 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
760 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
761 nigori().encryption_keybag()));
762 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
763 nigori().keybag_is_frozen());
764 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
765 nigori().encrypt_everything());
766 EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
767 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
768 nigori().passphrase_type());
770 syncable::ReadTransaction trans(FROM_HERE, directory());
771 EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
772 .Equals(ModelTypeSet::All()));
776 // If the server nigori is migrated but the local is not, preserve the server
777 // nigori.
778 TEST_F(ApplyControlDataUpdatesTest,
779 NigoriConflictServerMigrated) {
780 Cryptographer* cryptographer;
781 ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
782 KeyParams old_params = {"localhost", "dummy", "old"};
783 KeyParams new_params = {"localhost", "dummy", "new"};
785 syncable::ReadTransaction trans(FROM_HERE, directory());
786 cryptographer = directory()->GetCryptographer(&trans);
787 EXPECT_TRUE(encrypted_types.Equals(
788 directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
791 // Set up the cryptographer with both new keys and old keys.
792 Cryptographer other_cryptographer(cryptographer->encryptor());
793 other_cryptographer.AddKey(old_params);
795 // Create server specifics with an migrated keystore passphrase type.
796 sync_pb::EntitySpecifics server_specifics;
797 sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
798 other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
799 server_nigori->set_encrypt_everything(false);
800 server_nigori->set_keybag_is_frozen(true);
801 server_nigori->set_passphrase_type(
802 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
803 server_nigori->mutable_keystore_decryptor_token();
804 int64 nigori_handle =
805 entry_factory_->CreateUnappliedNewItem(kNigoriTag,
806 server_specifics,
807 true);
809 // Add the old keys to the cryptographer.
810 cryptographer->AddKey(old_params);
811 cryptographer->AddKey(new_params);
812 EXPECT_TRUE(cryptographer->is_ready());
814 // Set up a local nigori with a migrated custom passphrase type
815 sync_pb::EntitySpecifics local_specifics;
816 sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
817 cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
818 local_nigori->set_encrypt_everything(false);
819 local_nigori->set_keybag_is_frozen(false);
820 ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
821 nigori_handle, local_specifics));
822 // Apply the update locally so that UpdateFromEncryptedTypes knows what state
823 // to use.
825 syncable::ReadTransaction trans(FROM_HERE, directory());
826 cryptographer = directory()->GetCryptographer(&trans);
827 directory()->GetNigoriHandler()->ApplyNigoriUpdate(
828 *local_nigori,
829 &trans);
832 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
833 EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
834 ApplyControlDataUpdates(directory());
835 EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
836 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
838 EXPECT_TRUE(cryptographer->is_ready());
839 // Note: we didn't overwrite the encryption keybag with the local keys. The
840 // sync encryption handler will do that when it detects that the new
841 // keybag is out of date (and update the keystore bootstrap if necessary).
842 EXPECT_FALSE(cryptographer->CanDecryptUsingDefaultKey(
843 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
844 nigori().encryption_keybag()));
845 EXPECT_TRUE(cryptographer->CanDecrypt(
846 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
847 nigori().encryption_keybag()));
848 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
849 nigori().keybag_is_frozen());
850 EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
851 nigori().has_keystore_decryptor_token());
852 EXPECT_EQ(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE,
853 entry_factory_->GetLocalSpecificsForItem(nigori_handle).
854 nigori().passphrase_type());
856 syncable::ReadTransaction trans(FROM_HERE, directory());
860 // Check that we can apply a simple control datatype node successfully.
861 TEST_F(ApplyControlDataUpdatesTest, ControlApply) {
862 std::string experiment_id = "experiment";
863 sync_pb::EntitySpecifics specifics;
864 specifics.mutable_experiments()->mutable_keystore_encryption()->
865 set_enabled(true);
866 int64 experiment_handle = entry_factory_->CreateUnappliedNewItem(
867 experiment_id, specifics, false);
868 ApplyControlDataUpdates(directory());
870 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(experiment_handle));
871 EXPECT_TRUE(
872 entry_factory_->GetLocalSpecificsForItem(experiment_handle).
873 experiments().keystore_encryption().enabled());
876 // Verify that we apply top level folders before their children.
877 TEST_F(ApplyControlDataUpdatesTest, ControlApplyParentBeforeChild) {
878 std::string parent_id = "parent";
879 std::string experiment_id = "experiment";
880 sync_pb::EntitySpecifics specifics;
881 specifics.mutable_experiments()->mutable_keystore_encryption()->
882 set_enabled(true);
883 int64 experiment_handle = entry_factory_->CreateUnappliedNewItemWithParent(
884 experiment_id, specifics, parent_id);
885 int64 parent_handle = entry_factory_->CreateUnappliedNewItem(
886 parent_id, specifics, true);
887 ApplyControlDataUpdates(directory());
889 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(parent_handle));
890 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(experiment_handle));
891 EXPECT_TRUE(
892 entry_factory_->GetLocalSpecificsForItem(experiment_handle).
893 experiments().keystore_encryption().enabled());
896 // Verify that we handle control datatype conflicts by preserving the server
897 // data.
898 TEST_F(ApplyControlDataUpdatesTest, ControlConflict) {
899 std::string experiment_id = "experiment";
900 sync_pb::EntitySpecifics local_specifics, server_specifics;
901 server_specifics.mutable_experiments()->mutable_keystore_encryption()->
902 set_enabled(true);
903 local_specifics.mutable_experiments()->mutable_keystore_encryption()->
904 set_enabled(false);
905 int64 experiment_handle = entry_factory_->CreateSyncedItem(
906 experiment_id, EXPERIMENTS, false);
907 entry_factory_->SetServerSpecificsForItem(experiment_handle,
908 server_specifics);
909 entry_factory_->SetLocalSpecificsForItem(experiment_handle,
910 local_specifics);
911 ApplyControlDataUpdates(directory());
913 EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(experiment_handle));
914 EXPECT_TRUE(
915 entry_factory_->GetLocalSpecificsForItem(experiment_handle).
916 experiments().keystore_encryption().enabled());
919 } // namespace syncer