OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "sync/test/fake_server/fake_server.h" | 5 #include "sync/test/fake_server/fake_server.h" |
6 | 6 |
| 7 #include <algorithm> |
7 #include <limits> | 8 #include <limits> |
8 #include <string> | 9 #include <string> |
9 #include <vector> | 10 #include <vector> |
10 | 11 |
11 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
12 #include "base/guid.h" | 13 #include "base/guid.h" |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
15 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
16 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
19 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
20 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
21 #include "net/http/http_status_code.h" | 22 #include "net/http/http_status_code.h" |
22 #include "sync/internal_api/public/base/model_type.h" | 23 #include "sync/internal_api/public/base/model_type.h" |
23 #include "sync/protocol/sync.pb.h" | 24 #include "sync/protocol/sync.pb.h" |
24 #include "sync/test/fake_server/bookmark_entity.h" | 25 #include "sync/test/fake_server/bookmark_entity.h" |
25 #include "sync/test/fake_server/permanent_entity.h" | 26 #include "sync/test/fake_server/permanent_entity.h" |
26 #include "sync/test/fake_server/tombstone_entity.h" | 27 #include "sync/test/fake_server/tombstone_entity.h" |
27 #include "sync/test/fake_server/unique_client_entity.h" | 28 #include "sync/test/fake_server/unique_client_entity.h" |
28 | 29 |
29 using std::string; | 30 using std::string; |
30 using std::vector; | 31 using std::vector; |
31 | 32 |
32 using base::AutoLock; | |
33 using syncer::GetModelType; | 33 using syncer::GetModelType; |
34 using syncer::ModelType; | 34 using syncer::ModelType; |
35 using syncer::ModelTypeSet; | 35 using syncer::ModelTypeSet; |
36 | 36 |
37 // The default birthday value. | 37 // The default birthday value. |
38 static const char kDefaultBirthday[] = "1234567890"; | 38 static const char kDefaultBirthday[] = "1234567890"; |
39 | 39 |
40 // The default keystore key. | 40 // The default keystore key. |
41 static const char kDefaultKeystoreKey[] = "1111111111111111"; | 41 static const char kDefaultKeystoreKey[] = "1111111111111111"; |
42 | 42 |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 SaveEntity(mobile_bookmarks_entity); | 231 SaveEntity(mobile_bookmarks_entity); |
232 return true; | 232 return true; |
233 } | 233 } |
234 | 234 |
235 void FakeServer::SaveEntity(FakeServerEntity* entity) { | 235 void FakeServer::SaveEntity(FakeServerEntity* entity) { |
236 delete entities_[entity->GetId()]; | 236 delete entities_[entity->GetId()]; |
237 entity->SetVersion(++version_); | 237 entity->SetVersion(++version_); |
238 entities_[entity->GetId()] = entity; | 238 entities_[entity->GetId()] = entity; |
239 } | 239 } |
240 | 240 |
241 int FakeServer::HandleCommand(const string& request, | 241 void FakeServer::HandleCommand(const string& request, |
242 int* response_code, | 242 const HandleCommandCallback& callback) { |
243 string* response) { | |
244 AutoLock lock(lock_); | |
245 | |
246 sync_pb::ClientToServerMessage message; | 243 sync_pb::ClientToServerMessage message; |
247 bool parsed = message.ParseFromString(request); | 244 bool parsed = message.ParseFromString(request); |
248 DCHECK(parsed); | 245 DCHECK(parsed); |
249 | 246 |
250 sync_pb::ClientToServerResponse response_proto; | 247 sync_pb::ClientToServerResponse response_proto; |
251 bool success; | 248 bool success; |
252 switch (message.message_contents()) { | 249 switch (message.message_contents()) { |
253 case sync_pb::ClientToServerMessage::GET_UPDATES: | 250 case sync_pb::ClientToServerMessage::GET_UPDATES: |
254 success = HandleGetUpdatesRequest(message.get_updates(), | 251 success = HandleGetUpdatesRequest(message.get_updates(), |
255 response_proto.mutable_get_updates()); | 252 response_proto.mutable_get_updates()); |
256 break; | 253 break; |
257 case sync_pb::ClientToServerMessage::COMMIT: | 254 case sync_pb::ClientToServerMessage::COMMIT: |
258 success = HandleCommitRequest(message.commit(), | 255 success = HandleCommitRequest(message.commit(), |
259 response_proto.mutable_commit()); | 256 response_proto.mutable_commit()); |
260 break; | 257 break; |
261 default: | 258 default: |
262 return net::ERR_NOT_IMPLEMENTED; | 259 callback.Run(net::ERR_NOT_IMPLEMENTED, 0, string());; |
| 260 return; |
263 } | 261 } |
264 | 262 |
265 if (!success) { | 263 if (!success) { |
266 // TODO(pvalenzuela): Add logging here so that tests have more info about | 264 // TODO(pvalenzuela): Add logging here so that tests have more info about |
267 // the failure. | 265 // the failure. |
268 return net::HTTP_BAD_REQUEST; | 266 callback.Run(net::ERR_FAILED, 0, string()); |
| 267 return; |
269 } | 268 } |
270 | 269 |
271 response_proto.set_error_code(sync_pb::SyncEnums::SUCCESS); | 270 response_proto.set_error_code(sync_pb::SyncEnums::SUCCESS); |
272 response_proto.set_store_birthday(birthday_); | 271 response_proto.set_store_birthday(birthday_); |
273 *response_code = net::HTTP_OK; | 272 callback.Run(0, net::HTTP_OK, response_proto.SerializeAsString()); |
274 *response = response_proto.SerializeAsString(); | |
275 return 0; | |
276 } | 273 } |
277 | 274 |
278 bool FakeServer::HandleGetUpdatesRequest( | 275 bool FakeServer::HandleGetUpdatesRequest( |
279 const sync_pb::GetUpdatesMessage& get_updates, | 276 const sync_pb::GetUpdatesMessage& get_updates, |
280 sync_pb::GetUpdatesResponse* response) { | 277 sync_pb::GetUpdatesResponse* response) { |
281 // TODO(pvalenzuela): Implement batching instead of sending all information | 278 // TODO(pvalenzuela): Implement batching instead of sending all information |
282 // at once. | 279 // at once. |
283 response->set_changes_remaining(0); | 280 response->set_changes_remaining(0); |
284 | 281 |
285 scoped_ptr<UpdateSieve> sieve = UpdateSieve::Create(get_updates); | 282 scoped_ptr<UpdateSieve> sieve = UpdateSieve::Create(get_updates); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 for (vector<string>::iterator it = keystore_keys_.begin(); | 314 for (vector<string>::iterator it = keystore_keys_.begin(); |
318 it != keystore_keys_.end(); ++it) { | 315 it != keystore_keys_.end(); ++it) { |
319 response->add_encryption_keys(*it); | 316 response->add_encryption_keys(*it); |
320 } | 317 } |
321 } | 318 } |
322 | 319 |
323 sieve->UpdateProgressMarkers(max_response_version, response); | 320 sieve->UpdateProgressMarkers(max_response_version, response); |
324 return true; | 321 return true; |
325 } | 322 } |
326 | 323 |
327 bool FakeServer::CommitEntity( | 324 string FakeServer::CommitEntity( |
328 const sync_pb::SyncEntity& client_entity, | 325 const sync_pb::SyncEntity& client_entity, |
329 sync_pb::CommitResponse_EntryResponse* entry_response, | 326 sync_pb::CommitResponse_EntryResponse* entry_response, |
330 string client_guid, | 327 string client_guid, |
331 std::map<string, string>* client_to_server_ids) { | 328 string parent_id) { |
332 if (client_entity.version() == 0 && client_entity.deleted()) { | 329 if (client_entity.version() == 0 && client_entity.deleted()) { |
333 return false; | 330 return string(); |
334 } | 331 } |
335 | 332 |
336 FakeServerEntity* entity; | 333 FakeServerEntity* entity; |
337 if (client_entity.deleted()) { | 334 if (client_entity.deleted()) { |
338 entity = TombstoneEntity::Create(client_entity.id_string()); | 335 entity = TombstoneEntity::Create(client_entity.id_string()); |
339 // TODO(pvalenzuela): Change the behavior of DeleteChilden so that it does | 336 // TODO(pvalenzuela): Change the behavior of DeleteChilden so that it does |
340 // not modify server data if it fails. | 337 // not modify server data if it fails. |
341 if (!DeleteChildren(client_entity.id_string())) { | 338 if (!DeleteChildren(client_entity.id_string())) { |
342 return false; | 339 return string(); |
343 } | 340 } |
344 } else if (GetModelType(client_entity) == syncer::NIGORI) { | 341 } else if (GetModelType(client_entity) == syncer::NIGORI) { |
345 // NIGORI is the only permanent item type that should be updated by the | 342 // NIGORI is the only permanent item type that should be updated by the |
346 // client. | 343 // client. |
347 entity = PermanentEntity::CreateUpdatedNigoriEntity( | 344 entity = PermanentEntity::CreateUpdatedNigoriEntity( |
348 client_entity, | 345 client_entity, |
349 entities_[client_entity.id_string()]); | 346 entities_[client_entity.id_string()]); |
350 } else if (client_entity.has_client_defined_unique_tag()) { | 347 } else if (client_entity.has_client_defined_unique_tag()) { |
351 if (entities_.find(client_entity.id_string()) != entities_.end()) { | 348 if (entities_.find(client_entity.id_string()) != entities_.end()) { |
352 entity = UniqueClientEntity::CreateUpdatedVersion( | 349 entity = UniqueClientEntity::CreateUpdatedVersion( |
353 client_entity, | 350 client_entity, |
354 entities_[client_entity.id_string()]); | 351 entities_[client_entity.id_string()]); |
355 } else { | 352 } else { |
356 entity = UniqueClientEntity::CreateNew(client_entity); | 353 entity = UniqueClientEntity::CreateNew(client_entity); |
357 } | 354 } |
358 } else { | 355 } else { |
359 string parent_id = client_entity.parent_id_string(); | |
360 if (client_to_server_ids->find(parent_id) != | |
361 client_to_server_ids->end()) { | |
362 parent_id = (*client_to_server_ids)[parent_id]; | |
363 } | |
364 // TODO(pvalenzuela): Validate entity's parent ID. | 356 // TODO(pvalenzuela): Validate entity's parent ID. |
365 if (entities_.find(client_entity.id_string()) != entities_.end()) { | 357 if (entities_.find(client_entity.id_string()) != entities_.end()) { |
366 entity = BookmarkEntity::CreateUpdatedVersion( | 358 entity = BookmarkEntity::CreateUpdatedVersion( |
367 client_entity, | 359 client_entity, |
368 entities_[client_entity.id_string()], | 360 entities_[client_entity.id_string()], |
369 parent_id); | 361 parent_id); |
370 } else { | 362 } else { |
371 entity = BookmarkEntity::CreateNew(client_entity, parent_id, client_guid); | 363 entity = BookmarkEntity::CreateNew(client_entity, parent_id, client_guid); |
372 } | 364 } |
373 } | 365 } |
374 | 366 |
375 if (entity == NULL) { | 367 if (entity == NULL) { |
376 // TODO(pvalenzuela): Add logging so that it is easier to determine why | 368 // TODO(pvalenzuela): Add logging so that it is easier to determine why |
377 // creation failed. | 369 // creation failed. |
378 return false; | 370 return string(); |
379 } | |
380 | |
381 // Record the ID if it was renamed. | |
382 if (client_entity.id_string() != entity->GetId()) { | |
383 (*client_to_server_ids)[client_entity.id_string()] = entity->GetId(); | |
384 } | 371 } |
385 | 372 |
386 SaveEntity(entity); | 373 SaveEntity(entity); |
387 BuildEntryResponseForSuccessfulCommit(entry_response, entity); | 374 BuildEntryResponseForSuccessfulCommit(entry_response, entity); |
388 return true; | 375 return entity->GetId(); |
389 } | 376 } |
390 | 377 |
391 void FakeServer::BuildEntryResponseForSuccessfulCommit( | 378 void FakeServer::BuildEntryResponseForSuccessfulCommit( |
392 sync_pb::CommitResponse_EntryResponse* entry_response, | 379 sync_pb::CommitResponse_EntryResponse* entry_response, |
393 FakeServerEntity* entity) { | 380 FakeServerEntity* entity) { |
394 entry_response->set_response_type(sync_pb::CommitResponse::SUCCESS); | 381 entry_response->set_response_type(sync_pb::CommitResponse::SUCCESS); |
395 entry_response->set_id_string(entity->GetId()); | 382 entry_response->set_id_string(entity->GetId()); |
396 | 383 |
397 if (entity->IsDeleted()) { | 384 if (entity->IsDeleted()) { |
398 entry_response->set_version(entity->GetVersion() + 1); | 385 entry_response->set_version(entity->GetVersion() + 1); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 } | 422 } |
436 | 423 |
437 return true; | 424 return true; |
438 } | 425 } |
439 | 426 |
440 bool FakeServer::HandleCommitRequest( | 427 bool FakeServer::HandleCommitRequest( |
441 const sync_pb::CommitMessage& commit, | 428 const sync_pb::CommitMessage& commit, |
442 sync_pb::CommitResponse* response) { | 429 sync_pb::CommitResponse* response) { |
443 std::map<string, string> client_to_server_ids; | 430 std::map<string, string> client_to_server_ids; |
444 string guid = commit.cache_guid(); | 431 string guid = commit.cache_guid(); |
| 432 ModelTypeSet committed_model_types; |
445 | 433 |
446 // TODO(pvalenzuela): Add validation of CommitMessage.entries. | 434 // TODO(pvalenzuela): Add validation of CommitMessage.entries. |
447 ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>::const_iterator it; | 435 ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>::const_iterator it; |
448 for (it = commit.entries().begin(); it != commit.entries().end(); ++it) { | 436 for (it = commit.entries().begin(); it != commit.entries().end(); ++it) { |
449 sync_pb::CommitResponse_EntryResponse* entry_response = | 437 sync_pb::CommitResponse_EntryResponse* entry_response = |
450 response->add_entryresponse(); | 438 response->add_entryresponse(); |
451 | 439 |
452 if (!CommitEntity(*it, entry_response, guid, &client_to_server_ids)) { | 440 sync_pb::SyncEntity client_entity = *it; |
| 441 string parent_id = client_entity.parent_id_string(); |
| 442 if (client_to_server_ids.find(parent_id) != |
| 443 client_to_server_ids.end()) { |
| 444 parent_id = client_to_server_ids[parent_id]; |
| 445 } |
| 446 |
| 447 string entity_id = CommitEntity(client_entity, |
| 448 entry_response, |
| 449 guid, |
| 450 parent_id); |
| 451 if (entity_id.empty()) { |
453 return false; | 452 return false; |
454 } | 453 } |
| 454 |
| 455 // Record the ID if it was renamed. |
| 456 if (entity_id != client_entity.id_string()) { |
| 457 client_to_server_ids[client_entity.id_string()] = entity_id; |
| 458 } |
| 459 FakeServerEntity* entity = entities_[entity_id]; |
| 460 committed_model_types.Put(entity->GetModelType()); |
455 } | 461 } |
456 | 462 |
| 463 FOR_EACH_OBSERVER(Observer, observers_, OnCommit(committed_model_types)); |
457 return true; | 464 return true; |
458 } | 465 } |
459 | 466 |
460 scoped_ptr<base::DictionaryValue> FakeServer::GetEntitiesAsDictionaryValue() { | 467 scoped_ptr<base::DictionaryValue> FakeServer::GetEntitiesAsDictionaryValue() { |
461 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue()); | 468 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue()); |
462 | 469 |
463 // Initialize an empty ListValue for all ModelTypes. | 470 // Initialize an empty ListValue for all ModelTypes. |
464 ModelTypeSet all_types = ModelTypeSet::All(); | 471 ModelTypeSet all_types = ModelTypeSet::All(); |
465 for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) { | 472 for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) { |
466 dictionary->Set(ModelTypeToString(it.Get()), new base::ListValue()); | 473 dictionary->Set(ModelTypeToString(it.Get()), new base::ListValue()); |
(...skipping 15 matching lines...) Expand all Loading... |
482 } | 489 } |
483 // TODO(pvalenzuela): Store more data for each entity so additional | 490 // TODO(pvalenzuela): Store more data for each entity so additional |
484 // verification can be performed. One example of additional verification | 491 // verification can be performed. One example of additional verification |
485 // is checking the correctness of the bookmark hierarchy. | 492 // is checking the correctness of the bookmark hierarchy. |
486 list_value->Append(new base::StringValue(entity->GetName())); | 493 list_value->Append(new base::StringValue(entity->GetName())); |
487 } | 494 } |
488 | 495 |
489 return dictionary.Pass(); | 496 return dictionary.Pass(); |
490 } | 497 } |
491 | 498 |
| 499 void FakeServer::AddObserver(Observer* observer) { |
| 500 observers_.AddObserver(observer); |
| 501 } |
| 502 |
| 503 void FakeServer::RemoveObserver(Observer* observer) { |
| 504 observers_.RemoveObserver(observer); |
| 505 } |
| 506 |
492 } // namespace fake_server | 507 } // namespace fake_server |
OLD | NEW |