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

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: Rebase + small fix 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
« no previous file with comments | « no previous file | chrome/browser/sync/engine/change_reorder_buffer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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, GetEncryptedDataTypes(&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 %"PRIuS"", i), false,
375 syncable::BOOKMARKS, 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 %"PRIuS"", i), false,
381 syncable::BOOKMARKS, 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 encrypted_types.insert(syncable::BOOKMARKS);
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, GetEncryptedDataTypes(&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, GetEncryptedDataTypes(&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 %"PRIuS"", i), false,
466 syncable::BOOKMARKS, 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 %"PRIuS"", i), false,
472 syncable::BOOKMARKS, 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 encrypted_types.insert(syncable::BOOKMARKS);
486 CreateUnappliedNewItem(syncable::ModelTypeToRootTag(syncable::NIGORI),
487 specifics, true);
488 Cryptographer* cryptographer =
489 session()->context()->directory_manager()->cryptographer();
490 EXPECT_FALSE(cryptographer->has_pending_keys());
491
492 {
493 // Ensure we have unsynced nodes that aren't properly encrypted.
494 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
495 ASSERT_TRUE(dir.good());
496 ReadTransaction trans(dir, __FILE__, __LINE__);
497 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
498 Syncer::UnsyncedMetaHandles handles;
499 SyncerUtil::GetUnsyncedEntries(&trans, &handles);
500 EXPECT_EQ(2*batch_s+1, handles.size());
501 }
502
503 apply_updates_command_.ExecuteImpl(session());
504
505 sessions::StatusController* status = session()->status_controller();
506 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE);
507 EXPECT_EQ(1, status->update_progress().AppliedUpdatesSize())
508 << "All updates should have been attempted";
509 EXPECT_EQ(1, status->conflict_progress().ConflictingItemsSize())
510 << "The unsynced chnages trigger a conflict with the nigori update.";
511 EXPECT_EQ(0, status->update_progress().SuccessfullyAppliedUpdateCount())
512 << "The nigori update should not be applied";
284 EXPECT_FALSE(cryptographer->is_ready()); 513 EXPECT_FALSE(cryptographer->is_ready());
285 EXPECT_TRUE(cryptographer->has_pending_keys()); 514 EXPECT_TRUE(cryptographer->has_pending_keys());
515 {
516 // Ensure the unsynced nodes are still not encrypted.
517 ScopedDirLookup dir(syncdb()->manager(), syncdb()->name());
518 ASSERT_TRUE(dir.good());
519 ReadTransaction trans(dir, __FILE__, __LINE__);
520
521 // Since we're in conflict, the specifics don't reflect the unapplied
522 // changes.
523 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
524 encrypted_types.clear();
525 EXPECT_EQ(encrypted_types, GetEncryptedDataTypes(&trans));
526
527 Syncer::UnsyncedMetaHandles handles;
528 SyncerUtil::GetUnsyncedEntries(&trans, &handles);
529 EXPECT_EQ(2*batch_s+1, handles.size());
530 }
286 } 531 }
287 532
288 } // namespace browser_sync 533 } // namespace browser_sync
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/sync/engine/change_reorder_buffer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698