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

Side by Side Diff: chrome/browser/sync/engine/apply_updates_command_unittest.cc

Issue 6465005: [Sync] Initial support for encrypting any datatype (no UI hookup yet). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments. Rest of unit tests. Created 9 years, 10 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/string_util.h"
5 #include "chrome/browser/sync/engine/apply_updates_command.h" 6 #include "chrome/browser/sync/engine/apply_updates_command.h"
7 #include "chrome/browser/sync/engine/syncer.h"
8 #include "chrome/browser/sync/engine/syncer_util.h"
6 #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" 9 #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h"
7 #include "chrome/browser/sync/sessions/sync_session.h" 10 #include "chrome/browser/sync/sessions/sync_session.h"
8 #include "chrome/browser/sync/syncable/directory_manager.h" 11 #include "chrome/browser/sync/syncable/directory_manager.h"
12 #include "chrome/browser/sync/syncable/nigori_util.h"
9 #include "chrome/browser/sync/syncable/syncable.h" 13 #include "chrome/browser/sync/syncable/syncable.h"
10 #include "chrome/browser/sync/syncable/syncable_id.h" 14 #include "chrome/browser/sync/syncable/syncable_id.h"
11 #include "chrome/test/sync/engine/syncer_command_test.h" 15 #include "chrome/test/sync/engine/syncer_command_test.h"
16 #include "chrome/test/sync/engine/test_id_factory.h"
12 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
13 18
14 namespace browser_sync { 19 namespace browser_sync {
15 20
16 using sessions::SyncSession; 21 using sessions::SyncSession;
17 using std::string; 22 using std::string;
18 using syncable::Entry; 23 using syncable::Entry;
24 using syncable::GetEncryptedDataTypesFromSyncer;
19 using syncable::Id; 25 using syncable::Id;
20 using syncable::MutableEntry; 26 using syncable::MutableEntry;
21 using syncable::ReadTransaction; 27 using syncable::ReadTransaction;
22 using syncable::ScopedDirLookup; 28 using syncable::ScopedDirLookup;
23 using syncable::UNITTEST; 29 using syncable::UNITTEST;
24 using syncable::WriteTransaction; 30 using syncable::WriteTransaction;
25 31
26 // A test fixture for tests exercising ApplyUpdatesCommand. 32 // A test fixture for tests exercising ApplyUpdatesCommand.
27 class ApplyUpdatesCommandTest : public SyncerCommandTest { 33 class ApplyUpdatesCommandTest : public SyncerCommandTest {
28 public: 34 public:
29 protected: 35 protected:
30 ApplyUpdatesCommandTest() : next_revision_(1) {} 36 ApplyUpdatesCommandTest() : next_revision_(1) {}
31 virtual ~ApplyUpdatesCommandTest() {} 37 virtual ~ApplyUpdatesCommandTest() {}
32 38
33 virtual void SetUp() { 39 virtual void SetUp() {
34 workers()->clear(); 40 workers()->clear();
35 mutable_routing_info()->clear(); 41 mutable_routing_info()->clear();
36 // GROUP_PASSIVE worker. 42 // GROUP_PASSIVE worker.
37 workers()->push_back(make_scoped_refptr(new ModelSafeWorker())); 43 workers()->push_back(make_scoped_refptr(new ModelSafeWorker()));
38 (*mutable_routing_info())[syncable::BOOKMARKS] = GROUP_PASSIVE; 44 (*mutable_routing_info())[syncable::BOOKMARKS] = GROUP_PASSIVE;
39 (*mutable_routing_info())[syncable::PASSWORDS] = GROUP_PASSIVE; 45 (*mutable_routing_info())[syncable::PASSWORDS] = GROUP_PASSIVE;
40 (*mutable_routing_info())[syncable::NIGORI] = GROUP_PASSIVE; 46 (*mutable_routing_info())[syncable::NIGORI] = GROUP_PASSIVE;
41 SyncerCommandTest::SetUp(); 47 SyncerCommandTest::SetUp();
42 } 48 }
43 49
44 // Create a new unapplied update. 50 // Create a new unapplied bookmark node with a parent.
45 void CreateUnappliedNewItemWithParent(const string& item_id, 51 void CreateUnappliedNewItemWithParent(const string& item_id,
46 const string& parent_id) { 52 const string& parent_id) {
47 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name()); 53 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
48 ASSERT_TRUE(dir.good()); 54 ASSERT_TRUE(dir.good());
49 WriteTransaction trans(dir, UNITTEST, __FILE__, __LINE__); 55 WriteTransaction trans(dir, UNITTEST, __FILE__, __LINE__);
50 MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM, 56 MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
51 Id::CreateFromServerId(item_id)); 57 Id::CreateFromServerId(item_id));
52 ASSERT_TRUE(entry.good()); 58 ASSERT_TRUE(entry.good());
53 entry.Put(syncable::SERVER_VERSION, next_revision_++); 59 entry.Put(syncable::SERVER_VERSION, next_revision_++);
54 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); 60 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true);
55 61
56 entry.Put(syncable::SERVER_NON_UNIQUE_NAME, item_id); 62 entry.Put(syncable::SERVER_NON_UNIQUE_NAME, item_id);
57 entry.Put(syncable::SERVER_PARENT_ID, Id::CreateFromServerId(parent_id)); 63 entry.Put(syncable::SERVER_PARENT_ID, Id::CreateFromServerId(parent_id));
58 entry.Put(syncable::SERVER_IS_DIR, true); 64 entry.Put(syncable::SERVER_IS_DIR, true);
59 sync_pb::EntitySpecifics default_bookmark_specifics; 65 sync_pb::EntitySpecifics default_bookmark_specifics;
60 default_bookmark_specifics.MutableExtension(sync_pb::bookmark); 66 default_bookmark_specifics.MutableExtension(sync_pb::bookmark);
61 entry.Put(syncable::SERVER_SPECIFICS, default_bookmark_specifics); 67 entry.Put(syncable::SERVER_SPECIFICS, default_bookmark_specifics);
62 } 68 }
63 69
70 // Create a new unapplied update without a parent.
64 void CreateUnappliedNewItem(const string& item_id, 71 void CreateUnappliedNewItem(const string& item_id,
65 const sync_pb::EntitySpecifics& specifics) { 72 const sync_pb::EntitySpecifics& specifics,
73 bool is_unique) {
66 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name()); 74 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
67 ASSERT_TRUE(dir.good()); 75 ASSERT_TRUE(dir.good());
68 WriteTransaction trans(dir, UNITTEST, __FILE__, __LINE__); 76 WriteTransaction trans(dir, UNITTEST, __FILE__, __LINE__);
69 MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM, 77 MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
70 Id::CreateFromServerId(item_id)); 78 Id::CreateFromServerId(item_id));
71 ASSERT_TRUE(entry.good()); 79 ASSERT_TRUE(entry.good());
72 entry.Put(syncable::SERVER_VERSION, next_revision_++); 80 entry.Put(syncable::SERVER_VERSION, next_revision_++);
73 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); 81 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true);
74
75 entry.Put(syncable::SERVER_NON_UNIQUE_NAME, item_id); 82 entry.Put(syncable::SERVER_NON_UNIQUE_NAME, item_id);
76 entry.Put(syncable::SERVER_PARENT_ID, syncable::kNullId); 83 entry.Put(syncable::SERVER_PARENT_ID, syncable::kNullId);
77 entry.Put(syncable::SERVER_IS_DIR, false); 84 entry.Put(syncable::SERVER_IS_DIR, false);
78 entry.Put(syncable::SERVER_SPECIFICS, specifics); 85 entry.Put(syncable::SERVER_SPECIFICS, specifics);
86 if (is_unique) // For top-level nodes.
87 entry.Put(syncable::UNIQUE_SERVER_TAG, item_id);
88 }
89
90 // Create an unsynced item in the database. If item_id is a local ID, it
91 // will be treated as a create-new. Otherwise, if it's a server ID, we'll
92 // fake the server data so that it looks like it exists on the server.
93 // Returns the methandle of the created item in |metahandle_out| if not NULL.
94 void CreateUnsyncedItem(const Id& item_id,
95 const Id& parent_id,
96 const string& name,
97 bool is_folder,
98 syncable::ModelType model_type,
99 int64* metahandle_out) {
100 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
101 ASSERT_TRUE(dir.good());
102 WriteTransaction trans(dir, UNITTEST, __FILE__, __LINE__);
103 Id predecessor_id = dir->GetLastChildId(&trans, parent_id);
104 MutableEntry entry(&trans, syncable::CREATE, parent_id, name);
105 ASSERT_TRUE(entry.good());
106 entry.Put(syncable::ID, item_id);
107 entry.Put(syncable::BASE_VERSION,
108 item_id.ServerKnows() ? next_revision_++ : 0);
109 entry.Put(syncable::IS_UNSYNCED, true);
110 entry.Put(syncable::IS_DIR, is_folder);
111 entry.Put(syncable::IS_DEL, false);
112 entry.Put(syncable::PARENT_ID, parent_id);
113 entry.PutPredecessor(predecessor_id);
114 sync_pb::EntitySpecifics default_specifics;
115 syncable::AddDefaultExtensionValue(model_type, &default_specifics);
116 entry.Put(syncable::SPECIFICS, default_specifics);
117 if (item_id.ServerKnows()) {
118 entry.Put(syncable::SERVER_SPECIFICS, default_specifics);
119 entry.Put(syncable::SERVER_IS_DIR, is_folder);
120 entry.Put(syncable::SERVER_PARENT_ID, parent_id);
121 entry.Put(syncable::SERVER_IS_DEL, false);
122 }
123 if (metahandle_out)
124 *metahandle_out = entry.Get(syncable::META_HANDLE);
79 } 125 }
80 126
81 ApplyUpdatesCommand apply_updates_command_; 127 ApplyUpdatesCommand apply_updates_command_;
82 128 TestIdFactory id_factory_;
83 private: 129 private:
84 int64 next_revision_; 130 int64 next_revision_;
85 DISALLOW_COPY_AND_ASSIGN(ApplyUpdatesCommandTest); 131 DISALLOW_COPY_AND_ASSIGN(ApplyUpdatesCommandTest);
86 }; 132 };
87 133
88 TEST_F(ApplyUpdatesCommandTest, Simple) { 134 TEST_F(ApplyUpdatesCommandTest, Simple) {
89 string root_server_id = syncable::kNullId.GetServerId(); 135 string root_server_id = syncable::kNullId.GetServerId();
90 CreateUnappliedNewItemWithParent("parent", root_server_id); 136 CreateUnappliedNewItemWithParent("parent", root_server_id);
91 CreateUnappliedNewItemWithParent("child", "parent"); 137 CreateUnappliedNewItemWithParent("child", "parent");
92 138
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 217
172 browser_sync::KeyParams params = {"localhost", "dummy", "foobar"}; 218 browser_sync::KeyParams params = {"localhost", "dummy", "foobar"};
173 cryptographer->AddKey(params); 219 cryptographer->AddKey(params);
174 220
175 sync_pb::EntitySpecifics specifics; 221 sync_pb::EntitySpecifics specifics;
176 sync_pb::PasswordSpecificsData data; 222 sync_pb::PasswordSpecificsData data;
177 data.set_origin("http://example.com"); 223 data.set_origin("http://example.com");
178 224
179 cryptographer->Encrypt(data, 225 cryptographer->Encrypt(data,
180 specifics.MutableExtension(sync_pb::password)->mutable_encrypted()); 226 specifics.MutableExtension(sync_pb::password)->mutable_encrypted());
181 CreateUnappliedNewItem("item", specifics); 227 CreateUnappliedNewItem("item", specifics, false);
182 228
183 apply_updates_command_.ExecuteImpl(session()); 229 apply_updates_command_.ExecuteImpl(session());
184 230
185 sessions::StatusController* status = session()->status_controller(); 231 sessions::StatusController* status = session()->status_controller();
186 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); 232 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE);
187 EXPECT_EQ(1, status->update_progress().AppliedUpdatesSize()) 233 EXPECT_EQ(1, status->update_progress().AppliedUpdatesSize())
188 << "All updates should have been attempted"; 234 << "All updates should have been attempted";
189 EXPECT_EQ(0, status->conflict_progress().ConflictingItemsSize()) 235 EXPECT_EQ(0, status->conflict_progress().ConflictingItemsSize())
190 << "No update should be in conflict because they're all decryptable"; 236 << "No update should be in conflict because they're all decryptable";
191 EXPECT_EQ(1, status->update_progress().SuccessfullyAppliedUpdateCount()) 237 EXPECT_EQ(1, status->update_progress().SuccessfullyAppliedUpdateCount())
192 << "The updates that can be decrypted should be applied"; 238 << "The updates that can be decrypted should be applied";
193 } 239 }
194 240
195 TEST_F(ApplyUpdatesCommandTest, UndecryptablePassword) { 241 TEST_F(ApplyUpdatesCommandTest, UndecryptablePassword) {
196 // Undecryptable password updates should not be applied. 242 // Undecryptable password updates should not be applied.
197 sync_pb::EntitySpecifics specifics; 243 sync_pb::EntitySpecifics specifics;
198 specifics.MutableExtension(sync_pb::password); 244 specifics.MutableExtension(sync_pb::password);
199 CreateUnappliedNewItem("item", specifics); 245 CreateUnappliedNewItem("item", specifics, false);
200 246
201 apply_updates_command_.ExecuteImpl(session()); 247 apply_updates_command_.ExecuteImpl(session());
202 248
203 sessions::StatusController* status = session()->status_controller(); 249 sessions::StatusController* status = session()->status_controller();
204 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); 250 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE);
205 EXPECT_EQ(1, status->update_progress().AppliedUpdatesSize()) 251 EXPECT_EQ(1, status->update_progress().AppliedUpdatesSize())
206 << "All updates should have been attempted"; 252 << "All updates should have been attempted";
207 EXPECT_EQ(1, status->conflict_progress().ConflictingItemsSize()) 253 EXPECT_EQ(1, status->conflict_progress().ConflictingItemsSize())
208 << "The updates that can't be decrypted should be in conflict"; 254 << "The updates that can't be decrypted should be in conflict";
209 EXPECT_EQ(0, status->update_progress().SuccessfullyAppliedUpdateCount()) 255 EXPECT_EQ(0, status->update_progress().SuccessfullyAppliedUpdateCount())
210 << "No update that can't be decrypted should be applied"; 256 << "No update that can't be decrypted should be applied";
211 } 257 }
212 258
213 TEST_F(ApplyUpdatesCommandTest, SomeUndecryptablePassword) { 259 TEST_F(ApplyUpdatesCommandTest, SomeUndecryptablePassword) {
214 // Only decryptable password updates should be applied. 260 // Only decryptable password updates should be applied.
215 { 261 {
216 Cryptographer* cryptographer = 262 Cryptographer* cryptographer =
217 session()->context()->directory_manager()->cryptographer(); 263 session()->context()->directory_manager()->cryptographer();
218 264
219 KeyParams params = {"localhost", "dummy", "foobar"}; 265 KeyParams params = {"localhost", "dummy", "foobar"};
220 cryptographer->AddKey(params); 266 cryptographer->AddKey(params);
221 267
222 sync_pb::EntitySpecifics specifics; 268 sync_pb::EntitySpecifics specifics;
223 sync_pb::PasswordSpecificsData data; 269 sync_pb::PasswordSpecificsData data;
224 data.set_origin("http://example.com/1"); 270 data.set_origin("http://example.com/1");
225 271
226 cryptographer->Encrypt(data, 272 cryptographer->Encrypt(data,
227 specifics.MutableExtension(sync_pb::password)->mutable_encrypted()); 273 specifics.MutableExtension(sync_pb::password)->mutable_encrypted());
228 CreateUnappliedNewItem("item1", specifics); 274 CreateUnappliedNewItem("item1", specifics, false);
229 } 275 }
230 { 276 {
231 // Create a new cryptographer, independent of the one in the session. 277 // Create a new cryptographer, independent of the one in the session.
232 Cryptographer cryptographer; 278 Cryptographer cryptographer;
233 KeyParams params = {"localhost", "dummy", "bazqux"}; 279 KeyParams params = {"localhost", "dummy", "bazqux"};
234 cryptographer.AddKey(params); 280 cryptographer.AddKey(params);
235 281
236 sync_pb::EntitySpecifics specifics; 282 sync_pb::EntitySpecifics specifics;
237 sync_pb::PasswordSpecificsData data; 283 sync_pb::PasswordSpecificsData data;
238 data.set_origin("http://example.com/2"); 284 data.set_origin("http://example.com/2");
239 285
240 cryptographer.Encrypt(data, 286 cryptographer.Encrypt(data,
241 specifics.MutableExtension(sync_pb::password)->mutable_encrypted()); 287 specifics.MutableExtension(sync_pb::password)->mutable_encrypted());
242 CreateUnappliedNewItem("item2", specifics); 288 CreateUnappliedNewItem("item2", specifics, false);
243 } 289 }
244 290
245 apply_updates_command_.ExecuteImpl(session()); 291 apply_updates_command_.ExecuteImpl(session());
246 292
247 sessions::StatusController* status = session()->status_controller(); 293 sessions::StatusController* status = session()->status_controller();
248 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); 294 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE);
249 EXPECT_EQ(2, status->update_progress().AppliedUpdatesSize()) 295 EXPECT_EQ(2, status->update_progress().AppliedUpdatesSize())
250 << "All updates should have been attempted"; 296 << "All updates should have been attempted";
251 EXPECT_EQ(1, status->conflict_progress().ConflictingItemsSize()) 297 EXPECT_EQ(1, status->conflict_progress().ConflictingItemsSize())
252 << "The decryptable password update should be applied"; 298 << "The decryptable password update should be applied";
253 EXPECT_EQ(1, status->update_progress().SuccessfullyAppliedUpdateCount()) 299 EXPECT_EQ(1, status->update_progress().SuccessfullyAppliedUpdateCount())
254 << "The undecryptable password update shouldn't be applied"; 300 << "The undecryptable password update shouldn't be applied";
255 } 301 }
256 302
257 TEST_F(ApplyUpdatesCommandTest, NigoriUpdate) { 303 TEST_F(ApplyUpdatesCommandTest, NigoriUpdate) {
304 syncable::ModelTypeSet encrypted_types;
305 {
306 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
307 ASSERT_TRUE(dir.good());
308 ReadTransaction trans(dir, __FILE__, __LINE__);
309 EXPECT_EQ(encrypted_types, GetEncryptedDataTypesFromSyncer(&trans));
310 }
311
258 // Nigori node updates should update the Cryptographer. 312 // Nigori node updates should update the Cryptographer.
259 Cryptographer other_cryptographer; 313 Cryptographer other_cryptographer;
260 KeyParams params = {"localhost", "dummy", "foobar"}; 314 KeyParams params = {"localhost", "dummy", "foobar"};
261 other_cryptographer.AddKey(params); 315 other_cryptographer.AddKey(params);
262 316
263 sync_pb::EntitySpecifics specifics; 317 sync_pb::EntitySpecifics specifics;
264 other_cryptographer.GetKeys( 318 sync_pb::NigoriSpecifics* nigori =
265 specifics.MutableExtension(sync_pb::nigori)->mutable_encrypted()); 319 specifics.MutableExtension(sync_pb::nigori);
266 320 other_cryptographer.GetKeys(nigori->mutable_encrypted());
267 CreateUnappliedNewItem("item", specifics); 321 nigori->set_encrypt_bookmarks(true);
322 encrypted_types.insert(syncable::BOOKMARKS);
323 encrypted_types.insert(syncable::PASSWORDS);
324 CreateUnappliedNewItem(syncable::ModelTypeToRootTag(syncable::NIGORI),
325 specifics, true);
268 326
269 Cryptographer* cryptographer = 327 Cryptographer* cryptographer =
270 session()->context()->directory_manager()->cryptographer(); 328 session()->context()->directory_manager()->cryptographer();
271 EXPECT_FALSE(cryptographer->has_pending_keys()); 329 EXPECT_FALSE(cryptographer->has_pending_keys());
272 330
273 apply_updates_command_.ExecuteImpl(session()); 331 apply_updates_command_.ExecuteImpl(session());
274 332
333 sessions::StatusController* status = session()->status_controller();
334 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE);
335 EXPECT_EQ(1, status->update_progress().AppliedUpdatesSize())
336 << "All updates should have been attempted";
337 EXPECT_EQ(0, status->conflict_progress().ConflictingItemsSize())
338 << "The nigori update shouldn't be in conflict";
339 EXPECT_EQ(1, status->update_progress().SuccessfullyAppliedUpdateCount())
340 << "The nigori update should be applied";
341
342 EXPECT_FALSE(cryptographer->is_ready());
343 EXPECT_TRUE(cryptographer->has_pending_keys());
344 }
345
346 TEST_F(ApplyUpdatesCommandTest, EncryptUnsyncedChanges) {
347 syncable::ModelTypeSet encrypted_types;
348 {
349 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
350 ASSERT_TRUE(dir.good());
351 ReadTransaction trans(dir, __FILE__, __LINE__);
352 EXPECT_EQ(encrypted_types, GetEncryptedDataTypesFromSyncer(&trans));
353
354 // With empty encrypted_types, this should be true.
355 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
356
357 Syncer::UnsyncedMetaHandles handles;
358 SyncerUtil::GetUnsyncedEntries(&trans, &handles);
359 EXPECT_TRUE(handles.empty());
360 }
361
362 // Create unsynced bookmarks without encryption.
363 // First item is a folder
364 Id folder_id = id_factory_.NewLocalId();
365 CreateUnsyncedItem(folder_id, id_factory_.root(), "folder",
366 true, syncable::BOOKMARKS, NULL);
367 // Next five items are children of the folder
368 size_t i;
369 size_t batch_s = 5;
370 for (i = 0; i < batch_s; ++i) {
371 CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
372 StringPrintf("Item %zu", i), false, syncable::BOOKMARKS,
373 NULL);
374 }
375 // Next five items are children of the root.
376 for (; i < 2*batch_s; ++i) {
377 CreateUnsyncedItem(id_factory_.NewLocalId(), id_factory_.root(),
378 StringPrintf("Item %zu", i), false, syncable::BOOKMARKS,
379 NULL);
380 }
381
382 Cryptographer* cryptographer =
383 session()->context()->directory_manager()->cryptographer();
384 KeyParams params = {"localhost", "dummy", "foobar"};
385 cryptographer->AddKey(params);
386 sync_pb::EntitySpecifics specifics;
387 sync_pb::NigoriSpecifics* nigori =
388 specifics.MutableExtension(sync_pb::nigori);
389 cryptographer->GetKeys(nigori->mutable_encrypted());
390 nigori->set_encrypt_bookmarks(true);
391 nigori->set_encrypt_passwords(true);
392 encrypted_types.insert(syncable::BOOKMARKS);
393 encrypted_types.insert(syncable::PASSWORDS);
394 CreateUnappliedNewItem(syncable::ModelTypeToRootTag(syncable::NIGORI),
395 specifics, true);
396 EXPECT_FALSE(cryptographer->has_pending_keys());
397 EXPECT_TRUE(cryptographer->is_ready());
398
399 {
400 // Ensure we have unsynced nodes that aren't properly encrypted.
401 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
402 ASSERT_TRUE(dir.good());
403 ReadTransaction trans(dir, __FILE__, __LINE__);
404 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
405
406 Syncer::UnsyncedMetaHandles handles;
407 SyncerUtil::GetUnsyncedEntries(&trans, &handles);
408 EXPECT_EQ(2*batch_s+1, handles.size());
409 }
410
411 apply_updates_command_.ExecuteImpl(session());
412
275 sessions::StatusController* status = session()->status_controller(); 413 sessions::StatusController* status = session()->status_controller();
276 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); 414 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE);
277 EXPECT_EQ(1, status->update_progress().AppliedUpdatesSize()) 415 EXPECT_EQ(1, status->update_progress().AppliedUpdatesSize())
278 << "All updates should have been attempted"; 416 << "All updates should have been attempted";
279 EXPECT_EQ(0, status->conflict_progress().ConflictingItemsSize()) 417 EXPECT_EQ(0, status->conflict_progress().ConflictingItemsSize())
280 << "The nigori update shouldn't be in conflict"; 418 << "The nigori update shouldn't be in conflict";
281 EXPECT_EQ(1, status->update_progress().SuccessfullyAppliedUpdateCount()) 419 EXPECT_EQ(1, status->update_progress().SuccessfullyAppliedUpdateCount())
282 << "The nigori update should be applied"; 420 << "The nigori update should be applied";
421 EXPECT_FALSE(cryptographer->has_pending_keys());
422 EXPECT_TRUE(cryptographer->is_ready());
423 {
424 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
425 ASSERT_TRUE(dir.good());
426 ReadTransaction trans(dir, __FILE__, __LINE__);
283 427
428 // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes
429 // should be encrypted now.
430 EXPECT_EQ(encrypted_types, GetEncryptedDataTypesFromSyncer(&trans));
431 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
432
433 Syncer::UnsyncedMetaHandles handles;
434 SyncerUtil::GetUnsyncedEntries(&trans, &handles);
435 EXPECT_EQ(2*batch_s+1, handles.size());
436 }
437 }
438
439 TEST_F(ApplyUpdatesCommandTest, CannotEncryptUnsyncedChanges) {
440 syncable::ModelTypeSet encrypted_types;
441 {
442 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
443 ASSERT_TRUE(dir.good());
444 ReadTransaction trans(dir, __FILE__, __LINE__);
445 EXPECT_EQ(encrypted_types, GetEncryptedDataTypesFromSyncer(&trans));
446
447 // With empty encrypted_types, this should be true.
448 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
449
450 Syncer::UnsyncedMetaHandles handles;
451 SyncerUtil::GetUnsyncedEntries(&trans, &handles);
452 EXPECT_TRUE(handles.empty());
453 }
454
455 // Create unsynced bookmarks without encryption.
456 // First item is a folder
457 Id folder_id = id_factory_.NewLocalId();
458 CreateUnsyncedItem(folder_id, id_factory_.root(), "folder", true,
459 syncable::BOOKMARKS, NULL);
460 // Next five items are children of the folder
461 size_t i;
462 size_t batch_s = 5;
463 for (i = 0; i < batch_s; ++i) {
464 CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
465 StringPrintf("Item %zu", i), false, syncable::BOOKMARKS,
466 NULL);
467 }
468 // Next five items are children of the root.
469 for (; i < 2*batch_s; ++i) {
470 CreateUnsyncedItem(id_factory_.NewLocalId(), id_factory_.root(),
471 StringPrintf("Item %zu", i), false, syncable::BOOKMARKS,
472 NULL);
473 }
474
475 // We encrypt with new keys, triggering the local cryptographer to be unready
476 // and unable to decrypt data (once updated).
477 Cryptographer other_cryptographer;
478 KeyParams params = {"localhost", "dummy", "foobar"};
479 other_cryptographer.AddKey(params);
480 sync_pb::EntitySpecifics specifics;
481 sync_pb::NigoriSpecifics* nigori =
482 specifics.MutableExtension(sync_pb::nigori);
483 other_cryptographer.GetKeys(nigori->mutable_encrypted());
484 nigori->set_encrypt_bookmarks(true);
485 nigori->set_encrypt_passwords(true);
486 encrypted_types.insert(syncable::BOOKMARKS);
487 encrypted_types.insert(syncable::PASSWORDS);
488 CreateUnappliedNewItem(syncable::ModelTypeToRootTag(syncable::NIGORI),
489 specifics, true);
490 Cryptographer* cryptographer =
491 session()->context()->directory_manager()->cryptographer();
492 EXPECT_FALSE(cryptographer->has_pending_keys());
493
494 {
495 // Ensure we have unsynced nodes that aren't properly encrypted.
496 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
497 ASSERT_TRUE(dir.good());
498 ReadTransaction trans(dir, __FILE__, __LINE__);
499 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
500 Syncer::UnsyncedMetaHandles handles;
501 SyncerUtil::GetUnsyncedEntries(&trans, &handles);
502 EXPECT_EQ(2*batch_s+1, handles.size());
503 }
504
505 apply_updates_command_.ExecuteImpl(session());
506
507 sessions::StatusController* status = session()->status_controller();
508 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE);
509 EXPECT_EQ(1, status->update_progress().AppliedUpdatesSize())
510 << "All updates should have been attempted";
511 EXPECT_EQ(1, status->conflict_progress().ConflictingItemsSize())
512 << "The unsynced chnages trigger a conflict with the nigori update.";
513 EXPECT_EQ(0, status->update_progress().SuccessfullyAppliedUpdateCount())
514 << "The nigori update should not be applied";
284 EXPECT_FALSE(cryptographer->is_ready()); 515 EXPECT_FALSE(cryptographer->is_ready());
285 EXPECT_TRUE(cryptographer->has_pending_keys()); 516 EXPECT_TRUE(cryptographer->has_pending_keys());
517 {
518 // Ensure the unsynced nodes are still not encrypted.
519 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
520 ASSERT_TRUE(dir.good());
521 ReadTransaction trans(dir, __FILE__, __LINE__);
522
523 // Since we're in conflict, the specifics don't reflect the unapplied
524 // changes.
525 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
526 encrypted_types.clear();
527 EXPECT_EQ(encrypted_types, GetEncryptedDataTypesFromSyncer(&trans));
528
529 Syncer::UnsyncedMetaHandles handles;
530 SyncerUtil::GetUnsyncedEntries(&trans, &handles);
531 EXPECT_EQ(2*batch_s+1, handles.size());
532 }
286 } 533 }
287 534
288 } // namespace browser_sync 535 } // namespace browser_sync
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/sync/engine/change_reorder_buffer.h » ('j') | chrome/browser/sync/engine/syncapi.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698