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

Side by Side Diff: components/sync/test/fake_server/fake_server.cc

Issue 2887343002: wip 3 (Closed)
Patch Set: cleanup Created 3 years, 6 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
OLDNEW
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 "components/sync/test/fake_server/fake_server.h" 5 #include "components/sync/test/fake_server/fake_server.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/guid.h" 12 #include "base/guid.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
19 #include "base/synchronization/lock.h" 19 #include "base/synchronization/lock.h"
20 #include "components/sync/test/fake_server/bookmark_entity.h" 20 #include "base/threading/thread_restrictions.h"
21 #include "components/sync/test/fake_server/permanent_entity.h" 21 #include "components/sync/engine_impl/net/server_connection_manager.h"
22 #include "components/sync/test/fake_server/tombstone_entity.h"
23 #include "components/sync/test/fake_server/unique_client_entity.h"
24 #include "net/base/net_errors.h" 22 #include "net/base/net_errors.h"
25 #include "net/http/http_status_code.h" 23 #include "net/http/http_status_code.h"
26 24
27 using std::string; 25 using std::string;
28 using std::vector; 26 using std::vector;
29 using syncer::GetModelType; 27 using syncer::GetModelType;
30 using syncer::GetModelTypeFromSpecifics; 28 using syncer::GetModelTypeFromSpecifics;
29 using syncer::LoopbackServerEntity;
31 using syncer::ModelType; 30 using syncer::ModelType;
32 using syncer::ModelTypeSet; 31 using syncer::ModelTypeSet;
33 32
34 namespace fake_server { 33 namespace fake_server {
35 34
36 class FakeServerEntity;
37
38 namespace {
39
40 // The default keystore key.
41 static const char kDefaultKeystoreKey[] = "1111111111111111";
42
43 // Properties of the bookmark bar permanent folder.
44 static const char kBookmarkBarFolderServerTag[] = "bookmark_bar";
45 static const char kBookmarkBarFolderName[] = "Bookmark Bar";
46
47 // Properties of the other bookmarks permanent folder.
48 static const char kOtherBookmarksFolderServerTag[] = "other_bookmarks";
49 static const char kOtherBookmarksFolderName[] = "Other Bookmarks";
50
51 // Properties of the synced bookmarks permanent folder.
52 static const char kSyncedBookmarksFolderServerTag[] = "synced_bookmarks";
53 static const char kSyncedBookmarksFolderName[] = "Synced Bookmarks";
54
55 // A filter used during GetUpdates calls to determine what information to
56 // send back to the client; filtering out old entities and tracking versions to
57 // use in response progress markers. Note that only the GetUpdatesMessage's
58 // from_progress_marker is used to determine this; legacy fields are ignored.
59 class UpdateSieve {
60 public:
61 explicit UpdateSieve(const sync_pb::GetUpdatesMessage& message)
62 : UpdateSieve(MessageToVersionMap(message)) {}
63 ~UpdateSieve() {}
64
65 // Sets the progress markers in |get_updates_response| based on the highest
66 // version between request progress markers and response entities.
67 void SetProgressMarkers(
68 sync_pb::GetUpdatesResponse* get_updates_response) const {
69 for (const auto& kv : response_version_map_) {
70 sync_pb::DataTypeProgressMarker* new_marker =
71 get_updates_response->add_new_progress_marker();
72 new_marker->set_data_type_id(
73 GetSpecificsFieldNumberFromModelType(kv.first));
74 new_marker->set_token(base::Int64ToString(kv.second));
75 }
76 }
77
78 // Determines whether the server should send an |entity| to the client as
79 // part of a GetUpdatesResponse. Update internal tracking of max versions as a
80 // side effect which will later be used to set response progress markers.
81 bool ClientWantsItem(const FakeServerEntity& entity) {
82 int64_t version = entity.GetVersion();
83 ModelType type = entity.model_type();
84 response_version_map_[type] =
85 std::max(response_version_map_[type], version);
86 auto it = request_version_map_.find(type);
87 return it == request_version_map_.end() ? false : it->second < version;
88 }
89
90 private:
91 using ModelTypeToVersionMap = std::map<ModelType, int64_t>;
92
93 static UpdateSieve::ModelTypeToVersionMap MessageToVersionMap(
94 const sync_pb::GetUpdatesMessage& get_updates_message) {
95 CHECK_GT(get_updates_message.from_progress_marker_size(), 0)
96 << "A GetUpdates request must have at least one progress marker.";
97 ModelTypeToVersionMap request_version_map;
98
99 for (int i = 0; i < get_updates_message.from_progress_marker_size(); i++) {
100 sync_pb::DataTypeProgressMarker marker =
101 get_updates_message.from_progress_marker(i);
102
103 int64_t version = 0;
104 // Let the version remain zero if there is no token or an empty token (the
105 // first request for this type).
106 if (marker.has_token() && !marker.token().empty()) {
107 bool parsed = base::StringToInt64(marker.token(), &version);
108 CHECK(parsed) << "Unable to parse progress marker token.";
109 }
110
111 ModelType model_type =
112 syncer::GetModelTypeFromSpecificsFieldNumber(marker.data_type_id());
113 DCHECK(request_version_map.find(model_type) == request_version_map.end());
114 request_version_map[model_type] = version;
115 }
116 return request_version_map;
117 }
118
119 explicit UpdateSieve(const ModelTypeToVersionMap request_version_map)
120 : request_version_map_(request_version_map),
121 response_version_map_(request_version_map) {}
122
123 // The largest versions the client has seen before this request, and is used
124 // to filter entities to send back to clients. The values in this map are not
125 // updated after being initially set. The presence of a type in this map is a
126 // proxy for the desire to receive results about this type.
127 const ModelTypeToVersionMap request_version_map_;
128
129 // The largest versions seen between client and server, ultimately used to
130 // send progress markers back to the client.
131 ModelTypeToVersionMap response_version_map_;
132 };
133
134 // Returns whether |entity| is deleted or permanent.
135 bool IsDeletedOrPermanent(const FakeServerEntity& entity) {
136 return entity.IsDeleted() || entity.IsPermanent();
137 }
138
139 } // namespace
140
141 FakeServer::FakeServer() 35 FakeServer::FakeServer()
142 : version_(0), 36 : authenticated_(true),
143 store_birthday_(0),
144 authenticated_(true),
145 error_type_(sync_pb::SyncEnums::SUCCESS), 37 error_type_(sync_pb::SyncEnums::SUCCESS),
146 alternate_triggered_errors_(false), 38 alternate_triggered_errors_(false),
147 request_counter_(0), 39 request_counter_(0),
148 network_enabled_(true), 40 network_enabled_(true),
149 weak_ptr_factory_(this) { 41 weak_ptr_factory_(this) {
150 Init(); 42 loopback_server_storage_ = base::MakeUnique<base::ScopedTempDir>();
43 DCHECK(loopback_server_storage_->CreateUniqueTempDir());
44 base::ThreadRestrictions::SetIOAllowed(true);
45 loopback_server_ = base::MakeUnique<syncer::LoopbackServer>(
46 loopback_server_storage_->GetPath().AppendASCII("profile.pb"));
47 loopback_server_->set_observer_for_tests(this);
151 } 48 }
152 49
153 FakeServer::~FakeServer() {} 50 FakeServer::~FakeServer() {}
154 51
155 void FakeServer::Init() {
156 keystore_keys_.push_back(kDefaultKeystoreKey);
157
158 const bool create_result = CreateDefaultPermanentItems();
159 DCHECK(create_result) << "Permanent items were not created successfully.";
160 }
161
162 bool FakeServer::CreatePermanentBookmarkFolder(const std::string& server_tag,
163 const std::string& name) {
164 DCHECK(thread_checker_.CalledOnValidThread());
165 std::unique_ptr<FakeServerEntity> entity =
166 PermanentEntity::Create(syncer::BOOKMARKS, server_tag, name,
167 ModelTypeToRootTag(syncer::BOOKMARKS));
168 if (!entity)
169 return false;
170
171 SaveEntity(std::move(entity));
172 return true;
173 }
174
175 bool FakeServer::CreateDefaultPermanentItems() {
176 // Permanent folders are always required for Bookmarks (hierarchical
177 // structure) and Nigori (data stored in permanent root folder).
178 ModelTypeSet permanent_folder_types =
179 ModelTypeSet(syncer::BOOKMARKS, syncer::NIGORI);
180
181 for (ModelTypeSet::Iterator it = permanent_folder_types.First(); it.Good();
182 it.Inc()) {
183 ModelType model_type = it.Get();
184
185 std::unique_ptr<FakeServerEntity> top_level_entity =
186 PermanentEntity::CreateTopLevel(model_type);
187 if (!top_level_entity) {
188 return false;
189 }
190 SaveEntity(std::move(top_level_entity));
191
192 if (model_type == syncer::BOOKMARKS) {
193 if (!CreatePermanentBookmarkFolder(kBookmarkBarFolderServerTag,
194 kBookmarkBarFolderName))
195 return false;
196 if (!CreatePermanentBookmarkFolder(kOtherBookmarksFolderServerTag,
197 kOtherBookmarksFolderName))
198 return false;
199 }
200 }
201
202 return true;
203 }
204
205 void FakeServer::UpdateEntityVersion(FakeServerEntity* entity) {
206 entity->SetVersion(++version_);
207 }
208
209 void FakeServer::SaveEntity(std::unique_ptr<FakeServerEntity> entity) {
210 UpdateEntityVersion(entity.get());
211 entities_[entity->id()] = std::move(entity);
212 }
213
214 void FakeServer::HandleCommand(const string& request, 52 void FakeServer::HandleCommand(const string& request,
215 const base::Closure& completion_closure, 53 const base::Closure& completion_closure,
216 int* error_code, 54 int* error_code,
217 int* response_code, 55 int* response_code,
218 std::string* response) { 56 std::string* response) {
219 DCHECK(thread_checker_.CalledOnValidThread()); 57 DCHECK(thread_checker_.CalledOnValidThread());
58
220 if (!network_enabled_) { 59 if (!network_enabled_) {
221 *error_code = net::ERR_FAILED; 60 *error_code = net::ERR_FAILED;
222 *response_code = net::ERR_FAILED; 61 *response_code = net::ERR_FAILED;
223 *response = string(); 62 *response = string();
224 completion_closure.Run(); 63 completion_closure.Run();
225 return; 64 return;
226 } 65 }
227 request_counter_++; 66 request_counter_++;
228 67
229 if (!authenticated_) { 68 if (!authenticated_) {
230 *error_code = 0; 69 *error_code = 0;
231 *response_code = net::HTTP_UNAUTHORIZED; 70 *response_code = net::HTTP_UNAUTHORIZED;
232 *response = string(); 71 *response = string();
233 completion_closure.Run(); 72 completion_closure.Run();
234 return; 73 return;
235 } 74 }
236 75
237 sync_pb::ClientToServerMessage message;
238 bool parsed = message.ParseFromString(request);
239 CHECK(parsed) << "Unable to parse the ClientToServerMessage.";
240
241 sync_pb::ClientToServerResponse response_proto; 76 sync_pb::ClientToServerResponse response_proto;
242 77 *response_code = 200;
243 if (message.has_store_birthday() && 78 *error_code = 0;
244 message.store_birthday() != GetStoreBirthday()) { 79 if (error_type_ != sync_pb::SyncEnums::SUCCESS &&
245 response_proto.set_error_code(sync_pb::SyncEnums::NOT_MY_BIRTHDAY); 80 ShouldSendTriggeredError()) {
246 } else if (error_type_ != sync_pb::SyncEnums::SUCCESS &&
247 ShouldSendTriggeredError()) {
248 response_proto.set_error_code(error_type_); 81 response_proto.set_error_code(error_type_);
249 } else if (triggered_actionable_error_.get() && ShouldSendTriggeredError()) { 82 } else if (triggered_actionable_error_.get() && ShouldSendTriggeredError()) {
250 sync_pb::ClientToServerResponse_Error* error = 83 sync_pb::ClientToServerResponse_Error* error =
251 response_proto.mutable_error(); 84 response_proto.mutable_error();
252 error->CopyFrom(*(triggered_actionable_error_.get())); 85 error->CopyFrom(*(triggered_actionable_error_.get()));
253 } else { 86 } else {
254 bool success = false; 87 sync_pb::ClientToServerMessage message;
88 bool parsed = message.ParseFromString(request);
89 CHECK(parsed) << "Unable to parse the ClientToServerMessage.";
255 switch (message.message_contents()) { 90 switch (message.message_contents()) {
256 case sync_pb::ClientToServerMessage::GET_UPDATES: 91 case sync_pb::ClientToServerMessage::GET_UPDATES:
257 last_getupdates_message_ = message; 92 last_getupdates_message_ = message;
258 success = HandleGetUpdatesRequest(message.get_updates(),
259 response_proto.mutable_get_updates());
260 break; 93 break;
261 case sync_pb::ClientToServerMessage::COMMIT: 94 case sync_pb::ClientToServerMessage::COMMIT:
262 last_commit_message_ = message; 95 last_commit_message_ = message;
263 success = HandleCommitRequest(message.commit(),
264 message.invalidator_client_id(),
265 response_proto.mutable_commit());
266 break;
267 case sync_pb::ClientToServerMessage::CLEAR_SERVER_DATA:
268 ClearServerData();
269 response_proto.mutable_clear_server_data();
270 success = true;
271 break; 96 break;
272 default: 97 default:
273 *error_code = net::ERR_NOT_IMPLEMENTED; 98 break;
274 *response_code = 0; 99 // Don't care.
275 *response = string();
276 completion_closure.Run();
277 return;
278 } 100 }
279 101
280 if (!success) { 102 int64_t response_code_large;
281 // TODO(pvalenzuela): Add logging here so that tests have more info about 103 syncer::HttpResponse::ServerConnectionCode server_status;
282 // the failure. 104 base::ThreadRestrictions::SetIOAllowed(true);
283 *error_code = net::ERR_FAILED; 105 loopback_server_->HandleCommand(request, &server_status,
284 *response_code = 0; 106 &response_code_large, response);
285 *response = string(); 107 *response_code = static_cast<int>(response_code_large);
286 completion_closure.Run(); 108 completion_closure.Run();
287 return; 109 return;
288 }
289
290 response_proto.set_error_code(sync_pb::SyncEnums::SUCCESS);
291 } 110 }
292 111
293 response_proto.set_store_birthday(GetStoreBirthday()); 112 response_proto.set_store_birthday(loopback_server_->GetStoreBirthday());
294
295 *error_code = 0;
296 *response_code = net::HTTP_OK;
297 *response = response_proto.SerializeAsString(); 113 *response = response_proto.SerializeAsString();
298 completion_closure.Run(); 114 completion_closure.Run();
299 } 115 }
300 116
301 bool FakeServer::GetLastCommitMessage(sync_pb::ClientToServerMessage* message) { 117 bool FakeServer::GetLastCommitMessage(sync_pb::ClientToServerMessage* message) {
302 if (!last_commit_message_.has_commit()) 118 if (!last_commit_message_.has_commit())
303 return false; 119 return false;
304 120
305 message->CopyFrom(last_commit_message_); 121 message->CopyFrom(last_commit_message_);
306 return true; 122 return true;
307 } 123 }
308 124
309 bool FakeServer::GetLastGetUpdatesMessage( 125 bool FakeServer::GetLastGetUpdatesMessage(
310 sync_pb::ClientToServerMessage* message) { 126 sync_pb::ClientToServerMessage* message) {
311 if (!last_getupdates_message_.has_get_updates()) 127 if (!last_getupdates_message_.has_get_updates())
312 return false; 128 return false;
313 129
314 message->CopyFrom(last_getupdates_message_); 130 message->CopyFrom(last_getupdates_message_);
315 return true; 131 return true;
316 } 132 }
317 133
318 bool FakeServer::HandleGetUpdatesRequest(
319 const sync_pb::GetUpdatesMessage& get_updates,
320 sync_pb::GetUpdatesResponse* response) {
321 // TODO(pvalenzuela): Implement batching instead of sending all information
322 // at once.
323 response->set_changes_remaining(0);
324
325 auto sieve = base::MakeUnique<UpdateSieve>(get_updates);
326
327 // This folder is called "Synced Bookmarks" by sync and is renamed
328 // "Mobile Bookmarks" by the mobile client UIs.
329 if (get_updates.create_mobile_bookmarks_folder() &&
330 !CreatePermanentBookmarkFolder(kSyncedBookmarksFolderServerTag,
331 kSyncedBookmarksFolderName)) {
332 return false;
333 }
334
335 bool send_encryption_keys_based_on_nigori = false;
336 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
337 ++it) {
338 const FakeServerEntity& entity = *it->second;
339 if (sieve->ClientWantsItem(entity)) {
340 sync_pb::SyncEntity* response_entity = response->add_entries();
341 entity.SerializeAsProto(response_entity);
342
343 if (entity.model_type() == syncer::NIGORI) {
344 send_encryption_keys_based_on_nigori =
345 response_entity->specifics().nigori().passphrase_type() ==
346 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
347 }
348 }
349 }
350
351 if (send_encryption_keys_based_on_nigori ||
352 get_updates.need_encryption_key()) {
353 for (vector<string>::iterator it = keystore_keys_.begin();
354 it != keystore_keys_.end(); ++it) {
355 response->add_encryption_keys(*it);
356 }
357 }
358
359 sieve->SetProgressMarkers(response);
360 return true;
361 }
362
363 string FakeServer::CommitEntity(
364 const sync_pb::SyncEntity& client_entity,
365 sync_pb::CommitResponse_EntryResponse* entry_response,
366 const string& client_guid,
367 const string& parent_id) {
368 if (client_entity.version() == 0 && client_entity.deleted()) {
369 return string();
370 }
371
372 std::unique_ptr<FakeServerEntity> entity;
373 if (client_entity.deleted()) {
374 entity = TombstoneEntity::Create(client_entity.id_string(),
375 client_entity.client_defined_unique_tag());
376 DeleteChildren(client_entity.id_string());
377 } else if (GetModelType(client_entity) == syncer::NIGORI) {
378 // NIGORI is the only permanent item type that should be updated by the
379 // client.
380 EntityMap::const_iterator iter = entities_.find(client_entity.id_string());
381 CHECK(iter != entities_.end());
382 entity = PermanentEntity::CreateUpdatedNigoriEntity(client_entity,
383 *iter->second);
384 } else if (client_entity.has_client_defined_unique_tag()) {
385 entity = UniqueClientEntity::Create(client_entity);
386 } else {
387 // TODO(pvalenzuela): Validate entity's parent ID.
388 EntityMap::const_iterator iter = entities_.find(client_entity.id_string());
389 if (iter != entities_.end()) {
390 entity = BookmarkEntity::CreateUpdatedVersion(client_entity,
391 *iter->second, parent_id);
392 } else {
393 entity = BookmarkEntity::CreateNew(client_entity, parent_id, client_guid);
394 }
395 }
396
397 if (!entity) {
398 // TODO(pvalenzuela): Add logging so that it is easier to determine why
399 // creation failed.
400 return string();
401 }
402
403 const std::string id = entity->id();
404 SaveEntity(std::move(entity));
405 BuildEntryResponseForSuccessfulCommit(id, entry_response);
406 return id;
407 }
408
409 void FakeServer::BuildEntryResponseForSuccessfulCommit(
410 const std::string& entity_id,
411 sync_pb::CommitResponse_EntryResponse* entry_response) {
412 EntityMap::const_iterator iter = entities_.find(entity_id);
413 CHECK(iter != entities_.end());
414 const FakeServerEntity& entity = *iter->second;
415 entry_response->set_response_type(sync_pb::CommitResponse::SUCCESS);
416 entry_response->set_id_string(entity.id());
417
418 if (entity.IsDeleted()) {
419 entry_response->set_version(entity.GetVersion() + 1);
420 } else {
421 entry_response->set_version(entity.GetVersion());
422 entry_response->set_name(entity.GetName());
423 }
424 }
425
426 bool FakeServer::IsChild(const string& id, const string& potential_parent_id) {
427 EntityMap::const_iterator iter = entities_.find(id);
428 if (iter == entities_.end()) {
429 // We've hit an ID (probably the imaginary root entity) that isn't stored
430 // by the server, so it can't be a child.
431 return false;
432 }
433
434 const FakeServerEntity& entity = *iter->second;
435 if (entity.GetParentId() == potential_parent_id)
436 return true;
437
438 // Recursively look up the tree.
439 return IsChild(entity.GetParentId(), potential_parent_id);
440 }
441
442 void FakeServer::DeleteChildren(const string& id) {
443 std::vector<std::unique_ptr<FakeServerEntity>> tombstones;
444 // Find all the children of id.
445 for (const auto& entity : entities_) {
446 if (IsChild(entity.first, id)) {
447 tombstones.push_back(TombstoneEntity::Create(
448 entity.first, entity.second->client_defined_unique_tag()));
449 }
450 }
451
452 for (auto& tombstone : tombstones) {
453 SaveEntity(std::move(tombstone));
454 }
455 }
456
457 bool FakeServer::HandleCommitRequest(const sync_pb::CommitMessage& commit,
458 const std::string& invalidator_client_id,
459 sync_pb::CommitResponse* response) {
460 std::map<string, string> client_to_server_ids;
461 string guid = commit.cache_guid();
462 ModelTypeSet committed_model_types;
463
464 // TODO(pvalenzuela): Add validation of CommitMessage.entries.
465 ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>::const_iterator it;
466 for (it = commit.entries().begin(); it != commit.entries().end(); ++it) {
467 sync_pb::CommitResponse_EntryResponse* entry_response =
468 response->add_entryresponse();
469
470 sync_pb::SyncEntity client_entity = *it;
471 string parent_id = client_entity.parent_id_string();
472 if (client_to_server_ids.find(parent_id) != client_to_server_ids.end()) {
473 parent_id = client_to_server_ids[parent_id];
474 }
475
476 const string entity_id =
477 CommitEntity(client_entity, entry_response, guid, parent_id);
478 if (entity_id.empty()) {
479 return false;
480 }
481
482 // Record the ID if it was renamed.
483 if (entity_id != client_entity.id_string()) {
484 client_to_server_ids[client_entity.id_string()] = entity_id;
485 }
486
487 EntityMap::const_iterator iter = entities_.find(entity_id);
488 CHECK(iter != entities_.end());
489 committed_model_types.Put(iter->second->model_type());
490 }
491
492 for (auto& observer : observers_)
493 observer.OnCommit(invalidator_client_id, committed_model_types);
494
495 return true;
496 }
497
498 std::unique_ptr<base::DictionaryValue> 134 std::unique_ptr<base::DictionaryValue>
499 FakeServer::GetEntitiesAsDictionaryValue() { 135 FakeServer::GetEntitiesAsDictionaryValue() {
500 DCHECK(thread_checker_.CalledOnValidThread()); 136 DCHECK(thread_checker_.CalledOnValidThread());
501 std::unique_ptr<base::DictionaryValue> dictionary( 137 return loopback_server_->GetEntitiesAsDictionaryValue();
502 new base::DictionaryValue());
503
504 // Initialize an empty ListValue for all ModelTypes.
505 ModelTypeSet all_types = ModelTypeSet::All();
506 for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) {
507 dictionary->Set(ModelTypeToString(it.Get()), new base::ListValue());
508 }
509
510 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
511 ++it) {
512 const FakeServerEntity& entity = *it->second;
513 if (IsDeletedOrPermanent(entity)) {
514 // Tombstones are ignored as they don't represent current data. Folders
515 // are also ignored as current verification infrastructure does not
516 // consider them.
517 continue;
518 }
519 base::ListValue* list_value;
520 if (!dictionary->GetList(ModelTypeToString(entity.model_type()),
521 &list_value)) {
522 return std::unique_ptr<base::DictionaryValue>();
523 }
524 // TODO(pvalenzuela): Store more data for each entity so additional
525 // verification can be performed. One example of additional verification
526 // is checking the correctness of the bookmark hierarchy.
527 list_value->AppendString(entity.GetName());
528 }
529
530 return dictionary;
531 } 138 }
532 139
533 std::vector<sync_pb::SyncEntity> FakeServer::GetSyncEntitiesByModelType( 140 std::vector<sync_pb::SyncEntity> FakeServer::GetSyncEntitiesByModelType(
534 ModelType model_type) { 141 ModelType model_type) {
535 std::vector<sync_pb::SyncEntity> sync_entities;
536 DCHECK(thread_checker_.CalledOnValidThread()); 142 DCHECK(thread_checker_.CalledOnValidThread());
537 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); 143 return loopback_server_->GetSyncEntitiesByModelType(model_type);
538 ++it) {
539 const FakeServerEntity& entity = *it->second;
540 if (!IsDeletedOrPermanent(entity) && entity.model_type() == model_type) {
541 sync_pb::SyncEntity sync_entity;
542 entity.SerializeAsProto(&sync_entity);
543 sync_entities.push_back(sync_entity);
544 }
545 }
546 return sync_entities;
547 } 144 }
548 145
549 void FakeServer::InjectEntity(std::unique_ptr<FakeServerEntity> entity) { 146 void FakeServer::InjectEntity(std::unique_ptr<LoopbackServerEntity> entity) {
550 DCHECK(thread_checker_.CalledOnValidThread()); 147 DCHECK(thread_checker_.CalledOnValidThread());
551 SaveEntity(std::move(entity)); 148 loopback_server_->SaveEntity(std::move(entity));
552 } 149 }
553 150
554 bool FakeServer::ModifyEntitySpecifics( 151 bool FakeServer::ModifyEntitySpecifics(
555 const std::string& id, 152 const std::string& id,
556 const sync_pb::EntitySpecifics& updated_specifics) { 153 const sync_pb::EntitySpecifics& updated_specifics) {
557 EntityMap::const_iterator iter = entities_.find(id); 154 return loopback_server_->ModifyEntitySpecifics(id, updated_specifics);
558 if (iter == entities_.end() ||
559 iter->second->model_type() !=
560 GetModelTypeFromSpecifics(updated_specifics)) {
561 return false;
562 }
563
564 FakeServerEntity* entity = iter->second.get();
565 entity->SetSpecifics(updated_specifics);
566 UpdateEntityVersion(entity);
567 return true;
568 }
569
570 bool FakeServer::ModifyBookmarkEntity(
571 const std::string& id,
572 const std::string& parent_id,
573 const sync_pb::EntitySpecifics& updated_specifics) {
574 EntityMap::const_iterator iter = entities_.find(id);
575 if (iter == entities_.end() ||
576 iter->second->model_type() != syncer::BOOKMARKS ||
577 GetModelTypeFromSpecifics(updated_specifics) != syncer::BOOKMARKS) {
578 return false;
579 }
580
581 BookmarkEntity* entity = static_cast<BookmarkEntity*>(iter->second.get());
582
583 entity->SetParentId(parent_id);
584 entity->SetSpecifics(updated_specifics);
585 if (updated_specifics.has_bookmark()) {
586 entity->SetName(updated_specifics.bookmark().title());
587 }
588 UpdateEntityVersion(entity);
589 return true;
590 } 155 }
591 156
592 void FakeServer::ClearServerData() { 157 void FakeServer::ClearServerData() {
593 DCHECK(thread_checker_.CalledOnValidThread()); 158 DCHECK(thread_checker_.CalledOnValidThread());
594 entities_.clear(); 159 loopback_server_->ClearServerData();
595 keystore_keys_.clear();
596 ++store_birthday_;
597 Init();
598 } 160 }
599 161
600 void FakeServer::SetAuthenticated() { 162 void FakeServer::SetAuthenticated() {
601 DCHECK(thread_checker_.CalledOnValidThread()); 163 DCHECK(thread_checker_.CalledOnValidThread());
602 authenticated_ = true; 164 authenticated_ = true;
603 } 165 }
604 166
605 void FakeServer::SetUnauthenticated() { 167 void FakeServer::SetUnauthenticated() {
606 DCHECK(thread_checker_.CalledOnValidThread()); 168 DCHECK(thread_checker_.CalledOnValidThread());
607 authenticated_ = false; 169 authenticated_ = false;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 void FakeServer::AddObserver(Observer* observer) { 227 void FakeServer::AddObserver(Observer* observer) {
666 DCHECK(thread_checker_.CalledOnValidThread()); 228 DCHECK(thread_checker_.CalledOnValidThread());
667 observers_.AddObserver(observer); 229 observers_.AddObserver(observer);
668 } 230 }
669 231
670 void FakeServer::RemoveObserver(Observer* observer) { 232 void FakeServer::RemoveObserver(Observer* observer) {
671 DCHECK(thread_checker_.CalledOnValidThread()); 233 DCHECK(thread_checker_.CalledOnValidThread());
672 observers_.RemoveObserver(observer); 234 observers_.RemoveObserver(observer);
673 } 235 }
674 236
237 void FakeServer::OnCommit(const std::string& committer_id,
238 syncer::ModelTypeSet committed_model_types) {
239 for (auto& observer : observers_)
240 observer.OnCommit(committer_id, committed_model_types);
241 }
242
675 void FakeServer::EnableNetwork() { 243 void FakeServer::EnableNetwork() {
676 DCHECK(thread_checker_.CalledOnValidThread()); 244 DCHECK(thread_checker_.CalledOnValidThread());
677 network_enabled_ = true; 245 network_enabled_ = true;
678 } 246 }
679 247
680 void FakeServer::DisableNetwork() { 248 void FakeServer::DisableNetwork() {
681 DCHECK(thread_checker_.CalledOnValidThread()); 249 DCHECK(thread_checker_.CalledOnValidThread());
682 network_enabled_ = false; 250 network_enabled_ = false;
683 } 251 }
684 252
685 std::string FakeServer::GetBookmarkBarFolderId() const {
686 DCHECK(thread_checker_.CalledOnValidThread());
687 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
688 ++it) {
689 FakeServerEntity* entity = it->second.get();
690 if (entity->GetName() == kBookmarkBarFolderName && entity->IsFolder() &&
691 entity->model_type() == syncer::BOOKMARKS) {
692 return entity->id();
693 }
694 }
695 NOTREACHED() << "Bookmark Bar entity not found.";
696 return "";
697 }
698
699 base::WeakPtr<FakeServer> FakeServer::AsWeakPtr() { 253 base::WeakPtr<FakeServer> FakeServer::AsWeakPtr() {
700 DCHECK(thread_checker_.CalledOnValidThread()); 254 DCHECK(thread_checker_.CalledOnValidThread());
701 return weak_ptr_factory_.GetWeakPtr(); 255 return weak_ptr_factory_.GetWeakPtr();
702 } 256 }
703 257
704 std::string FakeServer::GetStoreBirthday() const {
705 DCHECK(thread_checker_.CalledOnValidThread());
706 return base::Int64ToString(store_birthday_);
707 }
708
709 } // namespace fake_server 258 } // namespace fake_server
OLDNEW
« no previous file with comments | « components/sync/test/fake_server/fake_server.h ('k') | components/sync/test/fake_server/fake_server_entity.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698