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

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

Powered by Google App Engine
This is Rietveld 408576698