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

Unified Diff: components/sync/test/fake_server/fake_server.cc

Issue 2938553003: Revert of [sync] Replace FakeServer's implementation with LoopbackServer invocations. (Closed)
Patch Set: 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 side-by-side diff with in-line comments
Download patch
Index: components/sync/test/fake_server/fake_server.cc
diff --git a/components/sync/test/fake_server/fake_server.cc b/components/sync/test/fake_server/fake_server.cc
index c3462b1abc2a581b2b52895c7617f05797e2e3c0..de1cb209907ecd8ea7256b7e968a9d785c977fc4 100644
--- a/components/sync/test/fake_server/fake_server.cc
+++ b/components/sync/test/fake_server/fake_server.cc
@@ -17,8 +17,10 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
-#include "base/threading/thread_restrictions.h"
-#include "components/sync/engine_impl/net/server_connection_manager.h"
+#include "components/sync/test/fake_server/bookmark_entity.h"
+#include "components/sync/test/fake_server/permanent_entity.h"
+#include "components/sync/test/fake_server/tombstone_entity.h"
+#include "components/sync/test/fake_server/unique_client_entity.h"
#include "net/base/net_errors.h"
#include "net/http/http_status_code.h"
@@ -26,28 +28,188 @@
using std::vector;
using syncer::GetModelType;
using syncer::GetModelTypeFromSpecifics;
-using syncer::LoopbackServerEntity;
using syncer::ModelType;
using syncer::ModelTypeSet;
namespace fake_server {
+class FakeServerEntity;
+
+namespace {
+
+// The default keystore key.
+static const char kDefaultKeystoreKey[] = "1111111111111111";
+
+// Properties of the bookmark bar permanent folder.
+static const char kBookmarkBarFolderServerTag[] = "bookmark_bar";
+static const char kBookmarkBarFolderName[] = "Bookmark Bar";
+
+// Properties of the other bookmarks permanent folder.
+static const char kOtherBookmarksFolderServerTag[] = "other_bookmarks";
+static const char kOtherBookmarksFolderName[] = "Other Bookmarks";
+
+// Properties of the synced bookmarks permanent folder.
+static const char kSyncedBookmarksFolderServerTag[] = "synced_bookmarks";
+static const char kSyncedBookmarksFolderName[] = "Synced Bookmarks";
+
+// A filter used during GetUpdates calls to determine what information to
+// send back to the client; filtering out old entities and tracking versions to
+// use in response progress markers. Note that only the GetUpdatesMessage's
+// from_progress_marker is used to determine this; legacy fields are ignored.
+class UpdateSieve {
+ public:
+ explicit UpdateSieve(const sync_pb::GetUpdatesMessage& message)
+ : UpdateSieve(MessageToVersionMap(message)) {}
+ ~UpdateSieve() {}
+
+ // Sets the progress markers in |get_updates_response| based on the highest
+ // version between request progress markers and response entities.
+ void SetProgressMarkers(
+ sync_pb::GetUpdatesResponse* get_updates_response) const {
+ for (const auto& kv : response_version_map_) {
+ sync_pb::DataTypeProgressMarker* new_marker =
+ get_updates_response->add_new_progress_marker();
+ new_marker->set_data_type_id(
+ GetSpecificsFieldNumberFromModelType(kv.first));
+ new_marker->set_token(base::Int64ToString(kv.second));
+ }
+ }
+
+ // Determines whether the server should send an |entity| to the client as
+ // part of a GetUpdatesResponse. Update internal tracking of max versions as a
+ // side effect which will later be used to set response progress markers.
+ bool ClientWantsItem(const FakeServerEntity& entity) {
+ int64_t version = entity.GetVersion();
+ ModelType type = entity.model_type();
+ response_version_map_[type] =
+ std::max(response_version_map_[type], version);
+ auto it = request_version_map_.find(type);
+ return it == request_version_map_.end() ? false : it->second < version;
+ }
+
+ private:
+ using ModelTypeToVersionMap = std::map<ModelType, int64_t>;
+
+ static UpdateSieve::ModelTypeToVersionMap MessageToVersionMap(
+ const sync_pb::GetUpdatesMessage& get_updates_message) {
+ CHECK_GT(get_updates_message.from_progress_marker_size(), 0)
+ << "A GetUpdates request must have at least one progress marker.";
+ ModelTypeToVersionMap request_version_map;
+
+ for (int i = 0; i < get_updates_message.from_progress_marker_size(); i++) {
+ sync_pb::DataTypeProgressMarker marker =
+ get_updates_message.from_progress_marker(i);
+
+ int64_t version = 0;
+ // Let the version remain zero if there is no token or an empty token (the
+ // first request for this type).
+ if (marker.has_token() && !marker.token().empty()) {
+ bool parsed = base::StringToInt64(marker.token(), &version);
+ CHECK(parsed) << "Unable to parse progress marker token.";
+ }
+
+ ModelType model_type =
+ syncer::GetModelTypeFromSpecificsFieldNumber(marker.data_type_id());
+ DCHECK(request_version_map.find(model_type) == request_version_map.end());
+ request_version_map[model_type] = version;
+ }
+ return request_version_map;
+ }
+
+ explicit UpdateSieve(const ModelTypeToVersionMap request_version_map)
+ : request_version_map_(request_version_map),
+ response_version_map_(request_version_map) {}
+
+ // The largest versions the client has seen before this request, and is used
+ // to filter entities to send back to clients. The values in this map are not
+ // updated after being initially set. The presence of a type in this map is a
+ // proxy for the desire to receive results about this type.
+ const ModelTypeToVersionMap request_version_map_;
+
+ // The largest versions seen between client and server, ultimately used to
+ // send progress markers back to the client.
+ ModelTypeToVersionMap response_version_map_;
+};
+
+// Returns whether |entity| is deleted or permanent.
+bool IsDeletedOrPermanent(const FakeServerEntity& entity) {
+ return entity.IsDeleted() || entity.IsPermanent();
+}
+
+} // namespace
+
FakeServer::FakeServer()
- : authenticated_(true),
+ : version_(0),
+ store_birthday_(0),
+ authenticated_(true),
error_type_(sync_pb::SyncEnums::SUCCESS),
alternate_triggered_errors_(false),
request_counter_(0),
network_enabled_(true),
weak_ptr_factory_(this) {
- loopback_server_storage_ = base::MakeUnique<base::ScopedTempDir>();
- base::ThreadRestrictions::SetIOAllowed(true);
- DCHECK(loopback_server_storage_->CreateUniqueTempDir());
- loopback_server_ = base::MakeUnique<syncer::LoopbackServer>(
- loopback_server_storage_->GetPath().AppendASCII("profile.pb"));
- loopback_server_->set_observer_for_tests(this);
+ Init();
}
FakeServer::~FakeServer() {}
+
+void FakeServer::Init() {
+ keystore_keys_.push_back(kDefaultKeystoreKey);
+
+ const bool create_result = CreateDefaultPermanentItems();
+ DCHECK(create_result) << "Permanent items were not created successfully.";
+}
+
+bool FakeServer::CreatePermanentBookmarkFolder(const std::string& server_tag,
+ const std::string& name) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ std::unique_ptr<FakeServerEntity> entity =
+ PermanentEntity::Create(syncer::BOOKMARKS, server_tag, name,
+ ModelTypeToRootTag(syncer::BOOKMARKS));
+ if (!entity)
+ return false;
+
+ SaveEntity(std::move(entity));
+ return true;
+}
+
+bool FakeServer::CreateDefaultPermanentItems() {
+ // Permanent folders are always required for Bookmarks (hierarchical
+ // structure) and Nigori (data stored in permanent root folder).
+ ModelTypeSet permanent_folder_types =
+ ModelTypeSet(syncer::BOOKMARKS, syncer::NIGORI);
+
+ for (ModelTypeSet::Iterator it = permanent_folder_types.First(); it.Good();
+ it.Inc()) {
+ ModelType model_type = it.Get();
+
+ std::unique_ptr<FakeServerEntity> top_level_entity =
+ PermanentEntity::CreateTopLevel(model_type);
+ if (!top_level_entity) {
+ return false;
+ }
+ SaveEntity(std::move(top_level_entity));
+
+ if (model_type == syncer::BOOKMARKS) {
+ if (!CreatePermanentBookmarkFolder(kBookmarkBarFolderServerTag,
+ kBookmarkBarFolderName))
+ return false;
+ if (!CreatePermanentBookmarkFolder(kOtherBookmarksFolderServerTag,
+ kOtherBookmarksFolderName))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void FakeServer::UpdateEntityVersion(FakeServerEntity* entity) {
+ entity->SetVersion(++version_);
+}
+
+void FakeServer::SaveEntity(std::unique_ptr<FakeServerEntity> entity) {
+ UpdateEntityVersion(entity.get());
+ entities_[entity->id()] = std::move(entity);
+}
void FakeServer::HandleCommand(const string& request,
const base::Closure& completion_closure,
@@ -55,7 +217,6 @@
int* response_code,
std::string* response) {
DCHECK(thread_checker_.CalledOnValidThread());
-
if (!network_enabled_) {
*error_code = net::ERR_FAILED;
*response_code = net::ERR_FAILED;
@@ -73,43 +234,66 @@
return;
}
+ sync_pb::ClientToServerMessage message;
+ bool parsed = message.ParseFromString(request);
+ CHECK(parsed) << "Unable to parse the ClientToServerMessage.";
+
sync_pb::ClientToServerResponse response_proto;
- *response_code = 200;
- *error_code = 0;
- if (error_type_ != sync_pb::SyncEnums::SUCCESS &&
- ShouldSendTriggeredError()) {
+
+ if (message.has_store_birthday() &&
+ message.store_birthday() != GetStoreBirthday()) {
+ response_proto.set_error_code(sync_pb::SyncEnums::NOT_MY_BIRTHDAY);
+ } else if (error_type_ != sync_pb::SyncEnums::SUCCESS &&
+ ShouldSendTriggeredError()) {
response_proto.set_error_code(error_type_);
} else if (triggered_actionable_error_.get() && ShouldSendTriggeredError()) {
sync_pb::ClientToServerResponse_Error* error =
response_proto.mutable_error();
error->CopyFrom(*(triggered_actionable_error_.get()));
} else {
- sync_pb::ClientToServerMessage message;
- bool parsed = message.ParseFromString(request);
- CHECK(parsed) << "Unable to parse the ClientToServerMessage.";
+ bool success = false;
switch (message.message_contents()) {
case sync_pb::ClientToServerMessage::GET_UPDATES:
last_getupdates_message_ = message;
+ success = HandleGetUpdatesRequest(message.get_updates(),
+ response_proto.mutable_get_updates());
break;
case sync_pb::ClientToServerMessage::COMMIT:
last_commit_message_ = message;
+ success = HandleCommitRequest(message.commit(),
+ message.invalidator_client_id(),
+ response_proto.mutable_commit());
+ break;
+ case sync_pb::ClientToServerMessage::CLEAR_SERVER_DATA:
+ ClearServerData();
+ response_proto.mutable_clear_server_data();
+ success = true;
break;
default:
- break;
- // Don't care.
- }
-
- int64_t response_code_large;
- syncer::HttpResponse::ServerConnectionCode server_status;
- base::ThreadRestrictions::SetIOAllowed(true);
- loopback_server_->HandleCommand(request, &server_status,
- &response_code_large, response);
- *response_code = static_cast<int>(response_code_large);
- completion_closure.Run();
- return;
- }
-
- response_proto.set_store_birthday(loopback_server_->GetStoreBirthday());
+ *error_code = net::ERR_NOT_IMPLEMENTED;
+ *response_code = 0;
+ *response = string();
+ completion_closure.Run();
+ return;
+ }
+
+ if (!success) {
+ // TODO(pvalenzuela): Add logging here so that tests have more info about
+ // the failure.
+ *error_code = net::ERR_FAILED;
+ *response_code = 0;
+ *response = string();
+ completion_closure.Run();
+ return;
+ }
+
+ response_proto.set_error_code(sync_pb::SyncEnums::SUCCESS);
+ }
+
+ response_proto.set_store_birthday(GetStoreBirthday());
+
+ *error_code = 0;
+ *response_code = net::HTTP_OK;
*response = response_proto.SerializeAsString();
completion_closure.Run();
}
@@ -131,40 +315,287 @@
return true;
}
+bool FakeServer::HandleGetUpdatesRequest(
+ const sync_pb::GetUpdatesMessage& get_updates,
+ sync_pb::GetUpdatesResponse* response) {
+ // TODO(pvalenzuela): Implement batching instead of sending all information
+ // at once.
+ response->set_changes_remaining(0);
+
+ auto sieve = base::MakeUnique<UpdateSieve>(get_updates);
+
+ // This folder is called "Synced Bookmarks" by sync and is renamed
+ // "Mobile Bookmarks" by the mobile client UIs.
+ if (get_updates.create_mobile_bookmarks_folder() &&
+ !CreatePermanentBookmarkFolder(kSyncedBookmarksFolderServerTag,
+ kSyncedBookmarksFolderName)) {
+ return false;
+ }
+
+ bool send_encryption_keys_based_on_nigori = false;
+ for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
+ ++it) {
+ const FakeServerEntity& entity = *it->second;
+ if (sieve->ClientWantsItem(entity)) {
+ sync_pb::SyncEntity* response_entity = response->add_entries();
+ entity.SerializeAsProto(response_entity);
+
+ if (entity.model_type() == syncer::NIGORI) {
+ send_encryption_keys_based_on_nigori =
+ response_entity->specifics().nigori().passphrase_type() ==
+ sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
+ }
+ }
+ }
+
+ if (send_encryption_keys_based_on_nigori ||
+ get_updates.need_encryption_key()) {
+ for (vector<string>::iterator it = keystore_keys_.begin();
+ it != keystore_keys_.end(); ++it) {
+ response->add_encryption_keys(*it);
+ }
+ }
+
+ sieve->SetProgressMarkers(response);
+ return true;
+}
+
+string FakeServer::CommitEntity(
+ const sync_pb::SyncEntity& client_entity,
+ sync_pb::CommitResponse_EntryResponse* entry_response,
+ const string& client_guid,
+ const string& parent_id) {
+ if (client_entity.version() == 0 && client_entity.deleted()) {
+ return string();
+ }
+
+ std::unique_ptr<FakeServerEntity> entity;
+ if (client_entity.deleted()) {
+ entity = TombstoneEntity::Create(client_entity.id_string(),
+ client_entity.client_defined_unique_tag());
+ DeleteChildren(client_entity.id_string());
+ } else if (GetModelType(client_entity) == syncer::NIGORI) {
+ // NIGORI is the only permanent item type that should be updated by the
+ // client.
+ EntityMap::const_iterator iter = entities_.find(client_entity.id_string());
+ CHECK(iter != entities_.end());
+ entity = PermanentEntity::CreateUpdatedNigoriEntity(client_entity,
+ *iter->second);
+ } else if (client_entity.has_client_defined_unique_tag()) {
+ entity = UniqueClientEntity::Create(client_entity);
+ } else {
+ // TODO(pvalenzuela): Validate entity's parent ID.
+ EntityMap::const_iterator iter = entities_.find(client_entity.id_string());
+ if (iter != entities_.end()) {
+ entity = BookmarkEntity::CreateUpdatedVersion(client_entity,
+ *iter->second, parent_id);
+ } else {
+ entity = BookmarkEntity::CreateNew(client_entity, parent_id, client_guid);
+ }
+ }
+
+ if (!entity) {
+ // TODO(pvalenzuela): Add logging so that it is easier to determine why
+ // creation failed.
+ return string();
+ }
+
+ const std::string id = entity->id();
+ SaveEntity(std::move(entity));
+ BuildEntryResponseForSuccessfulCommit(id, entry_response);
+ return id;
+}
+
+void FakeServer::BuildEntryResponseForSuccessfulCommit(
+ const std::string& entity_id,
+ sync_pb::CommitResponse_EntryResponse* entry_response) {
+ EntityMap::const_iterator iter = entities_.find(entity_id);
+ CHECK(iter != entities_.end());
+ const FakeServerEntity& entity = *iter->second;
+ entry_response->set_response_type(sync_pb::CommitResponse::SUCCESS);
+ entry_response->set_id_string(entity.id());
+
+ if (entity.IsDeleted()) {
+ entry_response->set_version(entity.GetVersion() + 1);
+ } else {
+ entry_response->set_version(entity.GetVersion());
+ entry_response->set_name(entity.GetName());
+ }
+}
+
+bool FakeServer::IsChild(const string& id, const string& potential_parent_id) {
+ EntityMap::const_iterator iter = entities_.find(id);
+ if (iter == entities_.end()) {
+ // We've hit an ID (probably the imaginary root entity) that isn't stored
+ // by the server, so it can't be a child.
+ return false;
+ }
+
+ const FakeServerEntity& entity = *iter->second;
+ if (entity.GetParentId() == potential_parent_id)
+ return true;
+
+ // Recursively look up the tree.
+ return IsChild(entity.GetParentId(), potential_parent_id);
+}
+
+void FakeServer::DeleteChildren(const string& id) {
+ std::vector<std::unique_ptr<FakeServerEntity>> tombstones;
+ // Find all the children of id.
+ for (const auto& entity : entities_) {
+ if (IsChild(entity.first, id)) {
+ tombstones.push_back(TombstoneEntity::Create(
+ entity.first, entity.second->client_defined_unique_tag()));
+ }
+ }
+
+ for (auto& tombstone : tombstones) {
+ SaveEntity(std::move(tombstone));
+ }
+}
+
+bool FakeServer::HandleCommitRequest(const sync_pb::CommitMessage& commit,
+ const std::string& invalidator_client_id,
+ sync_pb::CommitResponse* response) {
+ std::map<string, string> client_to_server_ids;
+ string guid = commit.cache_guid();
+ ModelTypeSet committed_model_types;
+
+ // TODO(pvalenzuela): Add validation of CommitMessage.entries.
+ ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>::const_iterator it;
+ for (it = commit.entries().begin(); it != commit.entries().end(); ++it) {
+ sync_pb::CommitResponse_EntryResponse* entry_response =
+ response->add_entryresponse();
+
+ sync_pb::SyncEntity client_entity = *it;
+ string parent_id = client_entity.parent_id_string();
+ if (client_to_server_ids.find(parent_id) != client_to_server_ids.end()) {
+ parent_id = client_to_server_ids[parent_id];
+ }
+
+ const string entity_id =
+ CommitEntity(client_entity, entry_response, guid, parent_id);
+ if (entity_id.empty()) {
+ return false;
+ }
+
+ // Record the ID if it was renamed.
+ if (entity_id != client_entity.id_string()) {
+ client_to_server_ids[client_entity.id_string()] = entity_id;
+ }
+
+ EntityMap::const_iterator iter = entities_.find(entity_id);
+ CHECK(iter != entities_.end());
+ committed_model_types.Put(iter->second->model_type());
+ }
+
+ for (auto& observer : observers_)
+ observer.OnCommit(invalidator_client_id, committed_model_types);
+
+ return true;
+}
+
std::unique_ptr<base::DictionaryValue>
FakeServer::GetEntitiesAsDictionaryValue() {
DCHECK(thread_checker_.CalledOnValidThread());
- return loopback_server_->GetEntitiesAsDictionaryValue();
+ std::unique_ptr<base::DictionaryValue> dictionary(
+ new base::DictionaryValue());
+
+ // Initialize an empty ListValue for all ModelTypes.
+ ModelTypeSet all_types = ModelTypeSet::All();
+ for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) {
+ dictionary->Set(ModelTypeToString(it.Get()),
+ base::MakeUnique<base::ListValue>());
+ }
+
+ for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
+ ++it) {
+ const FakeServerEntity& entity = *it->second;
+ if (IsDeletedOrPermanent(entity)) {
+ // Tombstones are ignored as they don't represent current data. Folders
+ // are also ignored as current verification infrastructure does not
+ // consider them.
+ continue;
+ }
+ base::ListValue* list_value;
+ if (!dictionary->GetList(ModelTypeToString(entity.model_type()),
+ &list_value)) {
+ return std::unique_ptr<base::DictionaryValue>();
+ }
+ // TODO(pvalenzuela): Store more data for each entity so additional
+ // verification can be performed. One example of additional verification
+ // is checking the correctness of the bookmark hierarchy.
+ list_value->AppendString(entity.GetName());
+ }
+
+ return dictionary;
}
std::vector<sync_pb::SyncEntity> FakeServer::GetSyncEntitiesByModelType(
ModelType model_type) {
- DCHECK(thread_checker_.CalledOnValidThread());
- return loopback_server_->GetSyncEntitiesByModelType(model_type);
-}
-
-void FakeServer::InjectEntity(std::unique_ptr<LoopbackServerEntity> entity) {
- DCHECK(thread_checker_.CalledOnValidThread());
- loopback_server_->SaveEntity(std::move(entity));
+ std::vector<sync_pb::SyncEntity> sync_entities;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
+ ++it) {
+ const FakeServerEntity& entity = *it->second;
+ if (!IsDeletedOrPermanent(entity) && entity.model_type() == model_type) {
+ sync_pb::SyncEntity sync_entity;
+ entity.SerializeAsProto(&sync_entity);
+ sync_entities.push_back(sync_entity);
+ }
+ }
+ return sync_entities;
+}
+
+void FakeServer::InjectEntity(std::unique_ptr<FakeServerEntity> entity) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ SaveEntity(std::move(entity));
}
bool FakeServer::ModifyEntitySpecifics(
const std::string& id,
const sync_pb::EntitySpecifics& updated_specifics) {
- return loopback_server_->ModifyEntitySpecifics(id, updated_specifics);
+ EntityMap::const_iterator iter = entities_.find(id);
+ if (iter == entities_.end() ||
+ iter->second->model_type() !=
+ GetModelTypeFromSpecifics(updated_specifics)) {
+ return false;
+ }
+
+ FakeServerEntity* entity = iter->second.get();
+ entity->SetSpecifics(updated_specifics);
+ UpdateEntityVersion(entity);
+ return true;
}
bool FakeServer::ModifyBookmarkEntity(
const std::string& id,
const std::string& parent_id,
const sync_pb::EntitySpecifics& updated_specifics) {
- return loopback_server_->ModifyBookmarkEntity(id, parent_id,
- updated_specifics);
+ EntityMap::const_iterator iter = entities_.find(id);
+ if (iter == entities_.end() ||
+ iter->second->model_type() != syncer::BOOKMARKS ||
+ GetModelTypeFromSpecifics(updated_specifics) != syncer::BOOKMARKS) {
+ return false;
+ }
+
+ BookmarkEntity* entity = static_cast<BookmarkEntity*>(iter->second.get());
+
+ entity->SetParentId(parent_id);
+ entity->SetSpecifics(updated_specifics);
+ if (updated_specifics.has_bookmark()) {
+ entity->SetName(updated_specifics.bookmark().title());
+ }
+ UpdateEntityVersion(entity);
+ return true;
}
void FakeServer::ClearServerData() {
DCHECK(thread_checker_.CalledOnValidThread());
- loopback_server_->ClearServerData();
+ entities_.clear();
+ keystore_keys_.clear();
+ ++store_birthday_;
+ Init();
}
void FakeServer::SetAuthenticated() {
@@ -242,12 +673,6 @@
observers_.RemoveObserver(observer);
}
-void FakeServer::OnCommit(const std::string& committer_id,
- syncer::ModelTypeSet committed_model_types) {
- for (auto& observer : observers_)
- observer.OnCommit(committer_id, committed_model_types);
-}
-
void FakeServer::EnableNetwork() {
DCHECK(thread_checker_.CalledOnValidThread());
network_enabled_ = true;
@@ -258,9 +683,28 @@
network_enabled_ = false;
}
+std::string FakeServer::GetBookmarkBarFolderId() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
+ ++it) {
+ FakeServerEntity* entity = it->second.get();
+ if (entity->GetName() == kBookmarkBarFolderName && entity->IsFolder() &&
+ entity->model_type() == syncer::BOOKMARKS) {
+ return entity->id();
+ }
+ }
+ NOTREACHED() << "Bookmark Bar entity not found.";
+ return "";
+}
+
base::WeakPtr<FakeServer> FakeServer::AsWeakPtr() {
DCHECK(thread_checker_.CalledOnValidThread());
return weak_ptr_factory_.GetWeakPtr();
}
+std::string FakeServer::GetStoreBirthday() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return base::Int64ToString(store_birthday_);
+}
+
} // namespace fake_server
« 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