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

Unified Diff: chrome/browser/sync/internal_api/syncapi_unittest.cc

Issue 8759019: [Sync] Add intelligent re-encryption support. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Self review Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sync/internal_api/syncapi_unittest.cc
diff --git a/chrome/browser/sync/internal_api/syncapi_unittest.cc b/chrome/browser/sync/internal_api/syncapi_unittest.cc
index 6e3c296963837f23388ea3cb4d357eb60592b60a..66a71b9494619b107bf63193b5b5bbf9068e97ad 100644
--- a/chrome/browser/sync/internal_api/syncapi_unittest.cc
+++ b/chrome/browser/sync/internal_api/syncapi_unittest.cc
@@ -73,9 +73,13 @@ using browser_sync::sessions::SyncSessionSnapshot;
using browser_sync::WeakHandle;
using content::BrowserThread;
using syncable::GetAllRealModelTypes;
+using syncable::IS_DEL;
+using syncable::IS_UNSYNCED;
using syncable::kEncryptedString;
using syncable::ModelType;
using syncable::ModelTypeSet;
+using syncable::NON_UNIQUE_NAME;
+using syncable::SPECIFICS;
using test::ExpectDictStringValue;
using testing::_;
using testing::AnyNumber;
@@ -179,6 +183,37 @@ int64 MakeServerNodeForType(UserShare* share,
return entry.Get(syncable::META_HANDLE);
}
+// Simulates creating a "synced" node as a child of the root datatype node.
+int64 MakeServerNode(UserShare* share, ModelType model_type,
+ const std::string& client_tag,
+ const std::string& hashed_tag,
+ const sync_pb::EntitySpecifics& specifics) {
+ syncable::ScopedDirLookup dir(share->dir_manager.get(), share->name);
+ EXPECT_TRUE(dir.good());
+ syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir);
+ syncable::Entry root_entry(&trans, syncable::GET_BY_SERVER_TAG,
+ syncable::ModelTypeToRootTag(model_type));
+ EXPECT_TRUE(root_entry.good());
+ syncable::Id root_id = root_entry.Get(syncable::ID);
+ syncable::Id node_id = syncable::Id::CreateFromServerId(client_tag);
+ syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
+ node_id);
+ EXPECT_TRUE(entry.good());
+ entry.Put(syncable::BASE_VERSION, 1);
+ entry.Put(syncable::SERVER_VERSION, 1);
+ entry.Put(syncable::IS_UNAPPLIED_UPDATE, false);
+ entry.Put(syncable::SERVER_PARENT_ID, root_id);
+ entry.Put(syncable::PARENT_ID, root_id);
+ entry.Put(syncable::SERVER_IS_DIR, false);
+ entry.Put(syncable::IS_DIR, false);
+ entry.Put(syncable::SERVER_SPECIFICS, specifics);
+ entry.Put(syncable::NON_UNIQUE_NAME, client_tag);
+ entry.Put(syncable::UNIQUE_CLIENT_TAG, hashed_tag);
+ entry.Put(syncable::IS_DEL, false);
+ entry.Put(syncable::SPECIFICS, specifics);
+ return entry.Get(syncable::META_HANDLE);
+}
+
} // namespace
class SyncApiTest : public testing::Test {
@@ -651,6 +686,8 @@ class SyncNotifierMock : public sync_notifier::SyncNotifier {
MOCK_METHOD1(SendNotification, void(const syncable::ModelTypeSet&));
};
+} // namespace
+
class SyncManagerTest : public testing::Test,
public ModelSafeWorkerRegistrar,
public SyncManager::ChangeDelegate {
@@ -747,7 +784,7 @@ class SyncManagerTest : public testing::Test,
virtual void OnChangesComplete(syncable::ModelType model_type) OVERRIDE {}
// Helper methods.
- bool SetUpEncryption(bool write_to_nigori) {
+ bool SetUpEncryption(bool write_to_nigori, bool encrypt_everything) {
// Mock the Mac Keychain service. The real Keychain can block on user input.
#if defined(OS_MACOSX)
Encryptor::UseMockKeychain(true);
@@ -773,9 +810,12 @@ class SyncManagerTest : public testing::Test,
return false;
KeyParams params = {"localhost", "dummy", "foobar"};
cryptographer->AddKey(params);
+ if (encrypt_everything)
+ cryptographer->set_encrypt_everything();
if (write_to_nigori) {
sync_pb::NigoriSpecifics nigori;
cryptographer->GetKeys(nigori.mutable_encrypted());
+ cryptographer->UpdateNigoriFromEncryptedTypes(&nigori);
WriteNode node(&trans);
EXPECT_TRUE(node.InitByIdLookup(nigori_id));
node.SetNigoriSpecifics(nigori);
@@ -831,6 +871,26 @@ class SyncManagerTest : public testing::Test,
PumpLoop();
}
+ // Looks up an entry by client tag and resets IS_UNSYNCED value to false.
+ // Returns true if entry was previously unsynced, false if IS_UNSYNCED was
+ // already false.
+ bool ResetUnsyncedEntry(syncable::ModelType type,
+ const std::string& client_tag) {
+ UserShare* share = sync_manager_.GetUserShare();
+ syncable::ScopedDirLookup dir(share->dir_manager.get(), share->name);
+ EXPECT_TRUE(dir.good());
+ syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir);
+ const std::string hash = BaseNode::GenerateSyncableHash(type, client_tag);
+ syncable::MutableEntry entry(&trans, syncable::GET_BY_CLIENT_TAG,
+ hash);
+ EXPECT_TRUE(entry.good());
+ if (!entry.Get(IS_UNSYNCED))
+ return false;
+ else
+ entry.Put(IS_UNSYNCED, false);
+ return true;
+ }
+
private:
// Needed by |ui_thread_|.
MessageLoopForUI ui_loop_;
@@ -1205,7 +1265,7 @@ TEST_F(SyncManagerTest, OnIncomingNotification) {
}
TEST_F(SyncManagerTest, RefreshEncryptionReady) {
- EXPECT_TRUE(SetUpEncryption(true));
+ EXPECT_TRUE(SetUpEncryption(true, false));
EXPECT_CALL(observer_, OnEncryptionComplete());
sync_manager_.RefreshEncryption();
syncable::ModelTypeSet encrypted_types =
@@ -1236,7 +1296,7 @@ TEST_F(SyncManagerTest, RefreshEncryptionNotReady) {
// Attempt to refresh encryption when nigori is empty.
TEST_F(SyncManagerTest, RefreshEncryptionEmptyNigori) {
- EXPECT_TRUE(SetUpEncryption(false));
+ EXPECT_TRUE(SetUpEncryption(false, false));
EXPECT_CALL(observer_, OnEncryptionComplete());
sync_manager_.RefreshEncryption(); // Should write to nigori.
syncable::ModelTypeSet encrypted_types =
@@ -1256,7 +1316,7 @@ TEST_F(SyncManagerTest, RefreshEncryptionEmptyNigori) {
}
TEST_F(SyncManagerTest, EncryptDataTypesWithNoData) {
- EXPECT_TRUE(SetUpEncryption(true));
+ EXPECT_TRUE(SetUpEncryption(true, false));
EXPECT_CALL(observer_,
OnEncryptedTypesChanged(GetAllRealModelTypes(), true));
EXPECT_CALL(observer_, OnEncryptionComplete());
@@ -1266,7 +1326,7 @@ TEST_F(SyncManagerTest, EncryptDataTypesWithNoData) {
TEST_F(SyncManagerTest, EncryptDataTypesWithData) {
size_t batch_size = 5;
- EXPECT_TRUE(SetUpEncryption(true));
+ EXPECT_TRUE(SetUpEncryption(true, false));
// Create some unencrypted unsynced data.
int64 folder = MakeFolderWithParent(sync_manager_.GetUserShare(),
@@ -1372,7 +1432,7 @@ TEST_F(SyncManagerTest, EncryptDataTypesWithData) {
}
TEST_F(SyncManagerTest, SetPassphraseWithPassword) {
- EXPECT_TRUE(SetUpEncryption(true));
+ EXPECT_TRUE(SetUpEncryption(true, false));
{
WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
ReadNode root_node(&trans);
@@ -1401,7 +1461,7 @@ TEST_F(SyncManagerTest, SetPassphraseWithPassword) {
}
TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) {
- EXPECT_TRUE(SetUpEncryption(true));
+ EXPECT_TRUE(SetUpEncryption(true, false));
int64 node_id = 0;
std::string tag = "foo";
{
@@ -1431,11 +1491,9 @@ TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) {
}
}
-} // namespace
-
// Friended by WriteNode, so can't be in an anonymouse namespace.
TEST_F(SyncManagerTest, EncryptBookmarksWithLegacyData) {
- EXPECT_TRUE(SetUpEncryption(true));
+ EXPECT_TRUE(SetUpEncryption(true, false));
std::string title;
SyncAPINameToServerName("Google", &title);
std::string url = "http://www.google.com";
@@ -1537,4 +1595,116 @@ TEST_F(SyncManagerTest, EncryptBookmarksWithLegacyData) {
}
}
+// Verifies WriteNode::UpdateEntryWithEncryption does not make unnecessary
+// changes.
+TEST_F(SyncManagerTest, UpdateEntryWithEncryption) {
+ std::string client_tag = "title";
+ sync_pb::EntitySpecifics entity_specifics;
+ entity_specifics.MutableExtension(sync_pb::bookmark)->set_url("url");
+ entity_specifics.MutableExtension(sync_pb::bookmark)->set_title("title");
+ MakeServerNode(sync_manager_.GetUserShare(), syncable::BOOKMARKS, client_tag,
+ BaseNode::GenerateSyncableHash(syncable::BOOKMARKS,
+ client_tag),
+ entity_specifics);
+ // New node shouldn't start off unsynced.
+ EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag));
+ // Manually change to the same data. Should not set is_unsynced.
+ {
+ WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
+ WriteNode node(&trans);
+ EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag));
+ node.SetEntitySpecifics(entity_specifics);
+ }
+ EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag));
+ // Encrypt the datatatype, should set is_unsynced.
+ EXPECT_CALL(observer_,
+ OnEncryptedTypesChanged(GetAllRealModelTypes(), true));
+ EXPECT_CALL(observer_, OnEncryptionComplete());
+ EXPECT_TRUE(SetUpEncryption(true, true));
+ sync_manager_.RefreshEncryption();
+ {
+ ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
+ ReadNode node(&trans);
+ EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag));
+ const syncable::Entry* node_entry = node.GetEntry();
+ const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS);
+ EXPECT_TRUE(specifics.has_encrypted());
+ EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME));
+ Cryptographer* cryptographer = trans.GetCryptographer();
+ EXPECT_TRUE(cryptographer->is_ready());
+ EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
+ specifics.encrypted()));
+ }
+ EXPECT_TRUE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag));
+ // Set a new passphrase. Should set is_unsynced.
+ testing::Mock::VerifyAndClearExpectations(&observer_);
+ EXPECT_CALL(observer_, OnPassphraseAccepted(_));
+ EXPECT_CALL(observer_, OnEncryptionComplete());
+ sync_manager_.SetPassphrase("new_passphrase", true);
+ {
+ ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
+ ReadNode node(&trans);
+ EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag));
+ const syncable::Entry* node_entry = node.GetEntry();
+ const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS);
+ EXPECT_TRUE(specifics.has_encrypted());
+ EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME));
+ Cryptographer* cryptographer = trans.GetCryptographer();
+ EXPECT_TRUE(cryptographer->is_ready());
+ EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
+ specifics.encrypted()));
+ }
+ EXPECT_TRUE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag));
+ // Force a re-encrypt everything. Should not set is_unsynced.
+ testing::Mock::VerifyAndClearExpectations(&observer_);
+ EXPECT_CALL(observer_, OnEncryptionComplete());
+ sync_manager_.RefreshEncryption();
+ {
+ ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
+ ReadNode node(&trans);
+ EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag));
+ const syncable::Entry* node_entry = node.GetEntry();
+ const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS);
+ EXPECT_TRUE(specifics.has_encrypted());
+ EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME));
+ Cryptographer* cryptographer = trans.GetCryptographer();
+ EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
+ specifics.encrypted()));
+ }
+ EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag));
+ // Manually change to the same data. Should not set is_unsynced.
+ {
+ WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
+ WriteNode node(&trans);
+ EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag));
+ node.SetEntitySpecifics(entity_specifics);
+ const syncable::Entry* node_entry = node.GetEntry();
+ const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS);
+ EXPECT_TRUE(specifics.has_encrypted());
+ EXPECT_FALSE(node_entry->Get(IS_UNSYNCED));
+ EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME));
+ Cryptographer* cryptographer = trans.GetCryptographer();
+ EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
+ specifics.encrypted()));
+ }
+ EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag));
+ // Manually change to different data. Should set is_unsynced.
+ {
+ entity_specifics.MutableExtension(sync_pb::bookmark)->set_url("url2");
+ entity_specifics.MutableExtension(sync_pb::bookmark)->set_title("title2");
+ WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
+ WriteNode node(&trans);
+ EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag));
+ node.SetEntitySpecifics(entity_specifics);
+ const syncable::Entry* node_entry = node.GetEntry();
+ const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS);
+ EXPECT_TRUE(specifics.has_encrypted());
+ EXPECT_TRUE(node_entry->Get(IS_UNSYNCED));
+ EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME));
+ Cryptographer* cryptographer = trans.GetCryptographer();
+ EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
+ specifics.encrypted()));
+ }
+}
+
} // namespace browser_sync

Powered by Google App Engine
This is Rietveld 408576698