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

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

Powered by Google App Engine
This is Rietveld 408576698